A library for sending ad beacons from the client-side. Works with both traditional SSAI and HLS interstitials. Compatible with iOS/tvOS 15 and above.
Using Swift Package Manager, enter the URL of this package:
https://github.com/harmonicinc-com/client-side-ad-tracking-ios-lib
-
Import the library
import HarmonicClientSideAdTracking -
Create an
AdBeaconingSessionobject:let mySession = AdBeaconingSession()
-
Optionally, set the session's player to your own instance of AVPlayer:
let myAVPlayer = AVPlayer() mySession.player = myAVPlayer
-
Set the session's media URL to the master playlist of an HLS stream:
mySession.mediaUrl = "<hls-master-playlist-url>"
- Note that the
AdBeaconingSessionobject will then do the following:- Try to obtain a manifest URL with a session ID (if the provided
mediaUrldoesn't already contain one); - Try to obtain the corresponding metadata URL with the session ID.
- Try to obtain a manifest URL with a session ID (if the provided
- Note that the
-
Observe the session's
manifestUrlby using the.onReceive(_:perform:)method in SwiftUI (for UIKit, please see the example below). When it is set and not empty, create anAVPlayerItemwith the URL and set it in the player:if !manifestUrl.isEmpty { let myPlayerItem = AVPlayerItem(url: URL(string: manifestUrl)!) mySession.player.replaceCurrentItem(with: myPlayerItem) }
-
Create a
HarmonicAdTrackerobject and initialize it with the session created above:let adTracker: HarmonicAdTracker? adTracker = HarmonicAdTracker(session: mySession)
-
Start the ad tracker:
adTracker?.start()
-
Start playing and beacons will be sent when ads are played:
mySession.player.play()
-
You may observe the following information from the session instance:
- To get the URLs with the session ID:
URLs available:
let sessionInfo = mySession.sessionInfo
sessionInfo.mediaUrl // String sessionInfo.manifestUrl // String sessionInfo.adTrackingMetadataUrl // String
- To get the list of
AdBreaks returned from the ad metadata along with the status of the beaconing for each event.For example, in the firstlet adPods = mySession.adPods
AdBreakofadPods:In the firstadPods[0].id // String adPods[0].startTime // Double: millisecondsSince1970 adPods[0].duration // Double: milliseconds adPods[0].ads // [Ad]
AdofadPods[0].ads:In the firstads[0].id // String ads[0].startTime // Double: millisecondsSince1970 ads[0].duration // Double: milliseconds ads[0].trackingEvents // [TrackingEvent]
TrackingEventofads[0].trackingEvents:trackingEvents[0].event // EventType trackingEvents[0].startTime // Double: millisecondsSince1970 trackingEvents[0].duration // Double: milliseconds trackingEvents[0].signalingUrls // [String] trackingEvents[0].reportingState // ReportingState
- To get the latest DataRange returned from the ad metadata.
To get the time in
let latestDataRange = mySession.latestDataRange
millisecondsSince1970:latestDataRange.start // Double: millisecondsSince1970 latestDataRange.end // Double: millisecondsSince1970
- To get the status and information of the player.
Information available:
let playerObserver = mySession.playerObserver
playerObserver.currentDate // Date playerObserver.playhead // Double: millisecondsSince1970 playerObserver.primaryStatus // AVPlayer.TimeControlStatus playerObserver.hasInterstitialEvents // Bool playerObserver.interstitialStatus // AVPlayer.TimeControlStatus playerObserver.interstitialDate // Double: millisecondsSince1970 playerObserver.interstitialStoppedDate // Double: millisecondsSince1970 playerObserver.interstitialStartTime // Double: seconds playerObserver.interstitialStopTime // Double: seconds playerObserver.currentInterstitialDuration // Double: milliseconds
- To get the messages logged by the library.
For example, in the first
let logMessages = mySession.logMessages
LogMessage:logMessages[0].timeStamp // Double: secondsSince1970 logMessages[0].message // String logMessages[0].isError // Bool
- To get the URLs with the session ID:
-
Stop the ad tracker when it is not needed:
adTracker?.stop()
In these examples, ad beacons will be sent while the stream is being played, but no UI is shown to indicate the progress of beaconing.
import SwiftUI
import AVKit
import HarmonicClientSideAdTracking
struct ContentView: View {
@StateObject private var mySession = AdBeaconingSession()
@State private var adTracker: HarmonicAdTracker?
var body: some View {
VideoPlayer(player: mySession.player)
.onAppear {
mySession.mediaUrl = "<hls-master-playlist-url>"
adTracker = HarmonicAdTracker(session: mySession)
}
.onReceive(mySession.sessionInfo.$manifestUrl) { manifestUrl in
if !manifestUrl.isEmpty {
let myPlayerItem = AVPlayerItem(url: URL(string: manifestUrl)!)
mySession.player.replaceCurrentItem(with: myPlayerItem)
mySession.player.play()
adTracker?.start()
}
}
.onDisappear {
adTracker?.stop()
}
}
}import UIKit
import AVKit
import Combine
import HarmonicClientSideAdTracking
class ViewController: UIViewController {
private var mySession = AdBeaconingSession()
private var adTracker: HarmonicAdTracker?
private var sessionSub: AnyCancellable?
override func viewDidAppear(_ animated: Bool) {
mySession.mediaUrl = "<hls-master-playlist-url>"
adTracker = HarmonicAdTracker(session: mySession)
let controller = AVPlayerViewController()
controller.player = mySession.player
present(controller, animated: true)
}
override func viewDidLoad() {
super.viewDidLoad()
sessionSub = mySession.$sessionInfo.sink { [weak self] sessionInfo in
guard let self = self else { return }
if !sessionInfo.manifestUrl.isEmpty {
let myPlayerItem = AVPlayerItem(url: URL(string: sessionInfo.manifestUrl)!)
mySession.player.replaceCurrentItem(with: myPlayerItem)
mySession.player.play()
adTracker?.start()
}
}
}
override func viewWillAppear(_ animated: Bool) {
adTracker?.stop()
}
}The library consists of several SwiftUI views that are used in the demo project. They are used to show how to display the progress of beacon-sending, and are not required for the ad beaconing logic to work.
This view shows a list of AdBreakViews.
-
Each
AdBreakViewindicates an ad break, and shows a list ofAdViews, each representing an ad in this ad break. -
Each
AdViewindicates an ad, and shows a list ofTrackingEventViews, each representing a tracking event in this ad. -
Each
TrackingEventViewindicates a tracking event, and shows information for this particular tracking event, including:- The event name
- The signaling URLs
- The time of the event
- The state of the beaconing of this event, which may be
idle,connecting,done, orfailed
Shows information about playback:
- Playhead
- Time to next ad beack
- If interstitials are available:
- Last interstitial's event date
- Last interstitial's start time
- Last interstitial's end time
Also, the different URLs of the session:
- Media URL (set by the user)
- Manifest URL (the redirected URL with a session ID)
- Ad tracking metadata URL
Contains a VideoPlayer with a debug overlay showing the real-world time and the latency. It also reloads by creating a new instance of player when the session's automaticallyPreservesTimeOffsetFromLive option is changed.
A demo app (that can be run on both iOS and tvOS) on how this library (including the SwiftUI views) may be used is available at the following repository: https://github.com/harmonicinc-com/client-side-ad-tracking-ios