Mit IMA SDKs können Sie Multimedia-Anzeigen ganz einfach in Ihre Websites und Apps einbinden. IMA SDKs können Anzeigen von jedem VAST-kompatiblen Ad-Server anfordern und die Anzeigenwiedergabe in Ihren Apps verwalten. Mit IMA DAI SDKs senden Apps Streamanfragen für Anzeigen- und Contentvideos – entweder für VOD oder Livecontent. Das SDK gibt dann einen kombinierten Videostream zurück, sodass Sie in Ihrer App nicht mehr zwischen Anzeige- und Contentvideo wechseln müssen.
Gewünschte Lösung für die dynamische Anzeigenbereitstellung auswählen
In dieser Anleitung wird gezeigt, wie Sie mit dem IMA DAI SDK für Roku einen Live- oder VOD-Stream für die dynamische Anzeigenbereitstellung wiedergeben.
Pod-Auslieferung mit der dynamischen Anzeigenbereitstellung von IMA – Übersicht
Für die Implementierung der Pod-Auslieferung mithilfe der dynamischen Anzeigenbereitstellung von IMA sind zwei SDK-Hauptkomponenten erforderlich, die in diesem Leitfaden erläutert werden:
StreamRequest.createPodLiveStreamRequest()
/StreamRequest.createPodVodStreamRequest()
: Erstellt ein Objekt, das eine Streamanfrage an die Advertising-Server von Google definiert. Diese Anfragen geben einen Netzwerkcode an. Für Pod-Live-ima.StreamRequest
sind außerdem ein benutzerdefinierter Asset-Schlüssel und ein optionaler API-Schlüssel erforderlich.StreamManager
: Ein Objekt, das die Kommunikation zwischen dem Videostream und dem IMA DAI SDK steuert, z. B. das Auslösen von Tracking-Pings und die Weiterleitung von Streamereignissen an den Publisher.
Außerdem musst du eine Anfrage an deinen Server für Manifestbearbeitung senden, damit das Streammanifest für deine App abgerufen werden kann. Die genaue Vorgehensweise kann von VTP zu VTP variieren.
Voraussetzungen
- Lesen Sie auf unserer Kompatibilitätsseite nach, ob Ihr geeigneter Anwendungsfall unterstützt wird.
- Laden Sie unseren Beispielcode für Roku herunter.
- Stellen Sie den Beispielcode auf einem Roku-Gerät bereit, um zu prüfen, ob Ihre Entwicklungseinrichtung funktioniert.
Spielen Sie Ihr Video ab.
Mit dem Beispielvideoplayer wird standardmäßig ein Inhaltsvideo wiedergegeben. Stellen Sie den Beispielplayer auf Ihrem Roku-Gerät bereit, damit Ihre Entwicklungsumgebung richtig eingerichtet ist.
Videoplayer in einen Stream-Player für die dynamische Anzeigenbereitstellung umwandeln
Führe die folgenden Schritte aus, um einen Stream-Player zu implementieren.
sdk.xml erstellen
Fügen Sie Ihrem Projekt zusammen mit MainScene.xml
eine neue Datei namens Sdk.xml
hinzu und fügen Sie den folgenden Standardcode ein:
Sdk.xml
<?xml version = "1.0" encoding = "utf-8" ?>
<component name = "imasdk" extends = "Task">
<interface>
</interface>
<script type = "text/brightscript">
<![CDATA[
' Your code goes here.
]]>
</script>
</component>
Sie müssen beide Dateien (MainScene.xml
und Sdk.xml
) in diesem Leitfaden bearbeiten.
IMA DAI SDK-Framework laden
Fügen Sie zum Laden des Frameworks zu manifest
und Sdk.xml
Folgendes hinzu:
Manifest
bs_libs_required=googleima3
Sdk.xml
<?xml version = "1.0" encoding = "utf-8" ?>
<component name = "imasdk" extends = "Task">
<interface>
</interface>
<script type = "text/brightscript">
<![CDATA[
Library "IMA3.brs"
]]>
</script>
</component>
IMA DAI SDK initialisieren
Der erste Schritt zum Laden Ihres Streams für die dynamische Anzeigenbereitstellung mit IMA SDK besteht darin, das IMA DAI SDK zu laden und zu initialisieren. So wird das Script des IMA DAI SDK initialisiert.
Sdk.xml
<?xml version="1.0" encoding="utf-8" ?>
<component name="IMASDKTask" extends="Task">
<interface>
<field id="IMASDKInitialized" type="Boolean" />
<field id="errors" type="stringarray" />
</interface>
<script type = "text/brightscript">
<![CDATA[
Library "IMA3.brs"
sub init()
m.top.functionName = "runThread"
end sub
sub runThread()
if not m.top.IMASDKInitialized
initializeIMASDK()
end if
end sub
sub initializeIMASDK()
if m.sdk = invalid
m.sdk = New_IMASDK()
end if
m.top.IMASDKInitialized = true
end sub
]]>
</script>
</component>
Starten Sie nun diese Aufgabe in MainScene.xml
und entfernen Sie den Aufruf zum Laden des Contentstreams.
MainScene.xml
<?xml version="1.0" encoding="utf-8" ?>
<component extends="Scene" initialFocus="myVideo" name="MainScene">
<script type="text/brightscript">
<![CDATA[
function init()
m.video = m.top.findNode("myVideo")
m.video.notificationinterval = 1
runIMASDKTask()
end function
function runIMASDKTask()
m.IMASDKTask = createObject("roSGNode", "IMASDKTask")
m.IMASDKTask.observeField("IMASDKInitialized", "handleIMASDKInitialized")
m.IMASDKTask.observeField("errors", "handleIMASDKErrors")
m.IMASDKTask.control = "RUN"
end function
sub handleIMASDKInitialized()
' Follow your manifest manipulator (VTP) documentation to register a user
' streaming session if needed.
end sub
sub handleIMASDKErrors(message as object)
print "------ IMA DAI SDK failed ------"
if message <> invalid and message.getData() <> invalid
print "IMA DAI SDK Error ";message.getData()
end if
end sub
]]>
</script>
<children>
<Video height="720" id="myVideo" visible="false" width="1280"/>
</children>
</component>
IMA-Stream-Player erstellen
Als Nächstes müssen Sie Ihren vorhandenen roVideoScreen
verwenden, um einen IMA-Stream-Player zu erstellen.
Pod-Auslieferung im Livestream
Für Livestreams implementiert dieser Stream-Player drei Callback-Methoden: streamInitialized
, adBreakStarted
und adBreakEnded
.
Auch die Trickwiedergabe beim Laden des Streams deaktivieren Dadurch wird verhindert, dass Nutzer eine Pre-Roll in dem Moment überspringen, in dem sie gestartet wird, noch bevor das Ereignis „Werbeunterbrechung gestartet“ ausgelöst wird.
Sdk.xml
<?xml version="1.0" encoding="utf-8" ?>
<component name="IMASDKTask" extends="Task">
<interface>
<field id="IMASDKInitialized" type="Boolean" />
<field id="errors" type="stringarray" />
<field id="urlData" type="assocarray" />
<field id="adPlaying" type="Boolean" />
<field id="videoNode" type="Node" />
</interface>
<script type="text/brightscript">
...
sub runThread()
if not m.top.IMASDKInitialized
initializeIMASDK()
end if
setupPlayerCallbacks()
end sub
...
sub initializeIMASDK()
if m.ima = invalid
ima = New_IMASDK()
ima.initSdk()
m.ima = ima
end if
m.top.IMASDKInitialized = true
end sub
sub setupPlayerCallbacks()
m.player = m.ima.createPlayer()
m.player.top = m.top
m.player.streamInitialized = function(urlData)
m.top.videoNode.enableTrickPlay = false
m.top.urlData = urlData
end function
m.player.adBreakStarted = function(adBreakInfo)
print "------ Ad break started ------"
m.top.adPlaying = true
m.top.videoNode.enableTrickPlay = false
end function
m.player.adBreakEnded = function(adBreakInfo)
print "------ Ad break ended ------"
m.top.adPlaying = false
m.top.videoNode.enableTrickPlay = true
end function
end sub
</script>
...
</component>
Pod-Auslieferung von VOD-Streams
Für VOD-Streams implementiert dieser Stream-Player vier Callback-Methoden: streamInitialized
, loadUrl
, adBreakStarted
und adBreakEnded
. Rufe im streamInitialized
-Callback StreamManager.loadThirdPartyStream()
auf. Andernfalls löst das SDK die Funktion loadUrl
nicht aus.
In diesem Schritt fordern Sie auch eine Stream-URL von Ihrem Videotechnologiepartner (VTP) mit einer Stream-ID an, die in loadAdPodStream()
abgerufen wird. Rufen Sie dann StreamManager.loadThirdPartyStream()
mit dem Manifest des Anzeigen-Pods und allen von Ihrem VTP zurückgegebenen Untertiteln auf.
Auch die Trickwiedergabe beim Laden des Streams deaktivieren Dadurch wird verhindert, dass Nutzer eine Pre-Roll in dem Moment überspringen, in dem sie gestartet wird, noch bevor das Ereignis „Werbeunterbrechung gestartet“ ausgelöst wird.
Sdk.xml
<?xml version="1.0" encoding="utf-8" ?>
<component name="IMASDKTask" extends="Task">
<interface>
<field id="IMASDKInitialized" type="Boolean" />
<field id="errors" type="stringarray" />
<field id="adStitchedStreamInfo" type="assocarray" />
<field id="adPlaying" type="Boolean" />
<field id="videoNode" type="Node" />
<field id="streamParameters" type="assocarray" />
</interface>
<script type="text/brightscript">
...
sub runThread()
if not m.top.IMASDKInitialized
initializeIMASDK()
end if
setupPlayerCallbacks()
end sub
...
sub initializeIMASDK()
if m.ima = invalid
ima = New_IMASDK()
ima.initSdk()
m.ima = ima
end if
m.top.IMASDKInitialized = true
end sub
sub loadThirdPartyStream(adStitchedManifest as string, subtitleConfig as dynamic)
m.streamManager.loadThirdPartyStream(adStitchedManifest, subtitleConfig)
end sub
sub setupPlayerCallbacks()
m.player = m.ima.createPlayer()
m.player.top = m.top
m.player.streamInitialized = function(urlData)
adStitchedManifest = m.top.streamParameters.VTPManifest.replace("[[STREAMID]]", urlData.streamId)
loadThirdPartyStream(adStitchedManifest, m.top.streamParameters.subtitleConfig)
end function
m.player.loadUrl = function(streamInfo)
m.top.adStitchedStreamInfo = streamInfo
end function
m.player.adBreakStarted = function(adBreakInfo)
print "------ Ad break started ------"
m.top.adPlaying = true
m.top.videoNode.enableTrickPlay = false
end function
m.player.adBreakEnded = function(adBreakInfo)
print "------ Ad break ended ------"
m.top.adPlaying = false
m.top.videoNode.enableTrickPlay = true
end function
end sub
</script>
...
</component>
Anfrage für einen Live- oder VOD-Pod zur Auslieferung über einen Stream erstellen und ausführen
Sobald Sie einen Stream-Player haben, können Sie eine Streamanfrage erstellen und ausführen.
Dieses Beispiel enthält Daten für einen Pod-Bereitstellungsstream, der in m.testPodServingStream
gespeichert ist.
Pod-Auslieferung im Livestream
Speichern Sie im m.testPodServingStream
-Objekt die Parameter, die Google Ad Manager zur Identifizierung des betreffenden Streams benötigt, z. B. einen Netzwerkcode und einen benutzerdefinierten Assetschlüssel. Speichern Sie auch die Manifest-URL, die für den Zugriff auf den Server für die Manifestbearbeitung verwendet wird. In diesem Fall muss der Manifest-URL die Google Stream-ID hinzugefügt werden, nachdem die Streamanfrage zurückgegeben wurde.
Damit AdUI wie z. B. Datenschutzinfo-Symbole unterstützt werden kann, müssen Sie in Ihrer Anfrage auch einen Verweis auf den Knoten übergeben, der Ihr Inhaltsvideo enthält.
MainScene.xml
function init()
m.video = m.top.findNode("myVideo")
m.video.notificationinterval = 1
m.testPodServingStream = {
title: "Test live stream for DAI Pod Serving",
assetKey: "test-live-stream",
networkCode: "your-network-code",
manifest: "https://.../master.m3u8?stream_id=[[STREAMID]]",
apiKey: ""
}
runIMASDKTask()
end function
function runIMASDKTask()
m.IMASDKTask = createObject("roSGNode", "IMASDKTask")
m.IMASDKTask.streamParameters = m.testPodservingStream
m.IMASDKTask.videoNode = m.video
m.IMASDKTask.observeField("IMASDKInitialized", "handleIMASDKInitialized")
m.IMASDKTask.observeField("errors", "handleIMASDKErrors")
m.IMASDKTask.control = "RUN"
end function
Sdk.xml
<interface>
<field id="IMASDKInitialized" type="Boolean" />
<field id="errors" type="stringarray" />
<field id="urlData" type="assocarray" />
<field id="adPlaying" type="Boolean" />
<field id="videoNode" type="Node" />
<field id="streamParameters" type="assocarray" />
</interface>
...
sub runThread()
if not m.top.IMASDKInitialized
initializeIMASDK()
end if
setupPlayerCallbacks()
loadAdPodStream()
end sub
sub loadAdPodStream()
request = m.ima.CreatePodLiveStreamRequest(m.top.streamParameters.assetKey, m.top.streamParameters.networkCode, m.top.streamParameters.apiKey)
' Set the player object so that the request can trigger the player's
' callbacks at stream initialization or playback events.
request.player = m.player
' Set the video node for the IMA DAI SDK to create ad UI as its child nodes.
request.adUiNode = m.top.video
requestResult = m.ima.requestStream(request)
if requestResult <> invalid
print "Error requesting stream ";requestResult
return
end if
m.streamManager = invalid
while m.streamManager = invalid
sleep(50)
m.streamManager = m.ima.getStreamManager()
end while
if m.streamManager = invalid
errors = CreateObject("roArray", 1, True)
invalidStreamManagerError = "Invalid stream manager"
print invalidStreamManagerError
errors.push(invalidStreamManagerError)
m.top.errors = errors
return
end if
if m.streamManager["type"] <> invalid and m.streamManager["type"] = "error"
errors = CreateObject("roArray", 1, True)
print "Stream request returns an error. " ; m.streamManager["info"]
errors.push(m.streamManager["info"])
m.top.errors = errors
return
end if
setupStreamManager()
m.streamManager.start()
end sub
Pod-Auslieferung von VOD-Streams
Im m.testPodServingStream
-Objekt speichern Sie den Netzwerkcode, der in der Streamanfrage verwendet wird, damit Google Ad Manager eine Stream-ID bereitstellen kann. Speichern Sie auch die Manifest-URL, die für den Zugriff auf das nutzerspezifische Manifest auf Ihrem Manifestbearbeitungsserver verwendet wird.
Damit AdUI wie z. B. Datenschutzinfo-Symbole unterstützt werden kann, müssen Sie in Ihrer Anfrage auch einen Verweis auf den Knoten übergeben, der Ihr Inhaltsvideo enthält.
MainScene.xml
sub init()
m.video = m.top.findNode("myVideo")
m.video.notificationinterval = 1
m.testPodServingStream = {
title: "Pod Serving VOD Stream",
networkCode: "your-network-code",
VTPManifest: "https://.../manifest.m3u8?gam-stream-id=[[STREAMID]]",
subtitleConfig: []
}
runIMASDKTask()
end sub
sub runIMASDKTask()
m.IMASDKTask = createObject("roSGNode", "IMASDKTask")
m.IMASDKTask.streamParameters = m.testPodservingStream
m.IMASDKTask.videoNode = m.video
m.IMASDKTask.observeField("IMASDKInitialized", "handleIMASDKInitialized")
m.IMASDKTask.observeField("errors", "handleIMASDKErrors")
m.IMASDKTask.control = "RUN"
end sub
Sdk.xml
sub runThread()
if not m.top.IMASDKInitialized
initializeIMASDK()
end if
setupPlayerCallbacks()
loadAdPodStream()
end sub
sub loadAdPodStream()
request = m.ima.CreatePodVodStreamRequest(m.top.streamParameters.networkCode)
' Set the player object so that the request can trigger the player
' callbacks at stream initialization or playback events.
request.player = m.player
' Set the video node for the IMA DAI SDK to create ad UI as its child nodes.
request.adUiNode = m.top.video
requestResult = m.ima.requestStream(request)
if requestResult <> invalid
print "Error requesting stream ";requestResult
return
end if
m.streamManager = invalid
while m.streamManager = invalid
sleep(50)
m.streamManager = m.ima.getStreamManager()
end while
if m.streamManager = invalid
errors = CreateObject("roArray", 1, True)
invalidStreamManagerError = "Invalid stream manager"
print invalidStreamManagerError
errors.push(invalidStreamManagerError)
m.top.errors = errors
return
end if
if m.streamManager["type"] <> invalid and m.streamManager["type"] = "error"
errors = CreateObject("roArray", 1, True)
print "Stream request returns an error. " ; m.streamManager["info"]
errors.push(m.streamManager["info"])
m.top.errors = errors
return
end if
setupStreamManager()
m.streamManager.start()
end sub
Event-Listener hinzufügen und Stream starten
Pod-Auslieferung im Livestream
Nachdem Sie Ihren Stream angefordert haben, müssen Sie nur noch Event-Listener hinzufügen, um den Anzeigenfortschritt zu verfolgen, und Roku-Nachrichten an das SDK weiterleiten. Es ist wichtig, dass Sie alle Nachrichten an das SDK weiterleiten, damit die Anzeigen korrekt wiedergegeben werden. Andernfalls werden die Anzeigenaufrufe falsch erfasst.
In diesem Schritt fügst du außerdem eine Funktion hinzu, um das [[STREAMID]]
-Makro durch die Stream-ID zu ersetzen und die fertige Manifest-Anfrage-URL an den Videoplayer zu übergeben.
Diese Implementierung ruft die Stream-ID in diesem Schritt ab. Abhängig von Ihrer VTP-Integration ist sie aber möglicherweise schon vor diesem Schritt verfügbar.
MainScene.xml
function runIMASDKTask()
m.IMASDKTask = createObject("roSGNode", "IMASDKTask")
m.IMASDKTask.streamParameters = m.testPodservingStream
m.IMASDKTask.videoNode = m.video
m.IMASDKTask.observeField("IMASDKInitialized", "handleIMASDKInitialized")
m.IMASDKTask.observeField("errors", "handleIMASDKErrors")
m.sdkTask.observeField("adStitchedStreamInfo", "loadAdStitchedStream")
m.sdkTask.control = "RUN"
end function
sub loadAdStitchedStream(message as object)
print "Ad pod stream information ";message
adPodStreamInfo = message.getData()
manifest = m.testPodservingStream.manifest.Replace("[[STREAMID]]", adPodStreamInfo.streamId)
playStream(manifest, adPodStreamInfo.format)
end sub
sub playStream(url as string, format as string)
vidContent = createObject("RoSGNode", "ContentNode")
vidContent.url = url
vidContent.title = m.testPodservingStream.title
vidContent.streamformat = format
m.video.content = vidContent
m.video.setFocus(true)
m.video.visible = true
m.video.control = "play"
m.video.EnableCookies()
end sub
Sdk.xml
sub runThread()
if not m.top.IMASDKInitialized
initializeIMASDK()
end if
setupPlayerCallbacks()
loadAdPodStream()
if m.streamManager <> invalid
runLoop()
end if
end sub
sub runLoop()
m.top.videoNode.timedMetaDataSelectionKeys = ["*"]
' IMPORTANT: Failure to listen to the position and timedmetadata fields
' could result in ad impressions not being reported.
m.port = CreateObject("roMessagePort")
m.top.videoNode.observeField("position", m.port)
m.top.videoNode.observeField("timedMetaData", m.port)
m.top.videoNode.observeField("timedMetaData2", m.port)
m.top.videoNode.observeField("state", m.port)
while True
msg = wait(1000, m.port)
if m.top.videoNode = invalid
print "exiting"
exit while
end if
m.streamManager.onMessage(msg)
currentTime = m.top.videoNode.position
if currentTime > 3 And not m.top.adPlaying
m.top.videoNode.enableTrickPlay = true
end if
end while
end sub
sub setupStreamManager()
m.streamManager.addEventListener(m.sdk.AdEvent.ERROR, errorCallback)
m.streamManager.addEventListener(m.sdk.AdEvent.START, startCallback)
m.streamManager.addEventListener(m.sdk.AdEvent.FIRST_QUARTILE, firstQuartileCallback)
m.streamManager.addEventListener(m.sdk.AdEvent.MIDPOINT, midpointCallback)
m.streamManager.addEventListener(m.sdk.AdEvent.THIRD_QUARTILE, thirdQuartileCallback)
m.streamManager.addEventListener(m.sdk.AdEvent.COMPLETE, completeCallback)
end sub
sub startCallback(ad as object)
print "Callback from SDK -- Start called - "
end sub
sub firstQuartileCallback(ad as object)
print "Callback from SDK -- First quartile called - "
end sub
sub midpointCallback(ad as object)
print "Callback from SDK -- Midpoint called - "
end sub
sub thirdQuartileCallback(ad as object)
print "Callback from SDK -- Third quartile called - "
end sub
sub completeCallback(ad as object)
print "Callback from SDK -- Complete called - "
end sub
function errorCallback(error as object)
print "Callback from SDK -- Error called - " ; error
m.errorState = True
end function
Pod-Auslieferung von VOD-Streams
Nachdem Sie Ihren Stream angefordert haben, müssen Sie nur noch Event-Listener hinzufügen, um den Anzeigenfortschritt zu verfolgen, und Roku-Nachrichten an das SDK weiterleiten. Es ist wichtig, dass Sie alle Nachrichten an das SDK weiterleiten, damit die Anzeigen korrekt wiedergegeben werden. Andernfalls werden die Anzeigenaufrufe falsch erfasst.
MainScene.xml
sub runIMASDKTask()
m.IMASDKTask = createObject("roSGNode", "IMASDKTask")
m.IMASDKTask.streamParameters = m.testPodservingStream
m.IMASDKTask.videoNode = m.video
m.IMASDKTask.observeField("IMASDKInitialized", "handleIMASDKInitialized")
m.IMASDKTask.observeField("errors", "handleIMASDKErrors")
m.sdkTask.observeField("adStitchedStreamInfo", "loadAdStitchedStream")
m.sdkTask.control = "RUN"
end sub
sub loadAdStitchedStream(message as object)
print "Ad pod stream information ";message
adPodStreamInfo = message.getData()
end sub
sub playStream(url as string, format as string, subtitleConfig as object)
vidContent = createObject("RoSGNode", "ContentNode")
vidContent.title = m.testPodservingStream.title
vidContent.url = url
vidContent.subtitleConfig = subtitleConfig
vidContent.streamformat = format
m.video.content = vidContent
m.video.setFocus(true)
m.video.visible = true
m.video.control = "play"
m.video.EnableCookies()
end sub
Sdk.xml
sub runThread()
if not m.top.IMASDKInitialized
initializeIMASDK()
end if
setupPlayerCallbacks()
loadAdPodStream()
if m.streamManager <> invalid
runLoop()
end if
end sub
sub runLoop()
m.top.videoNode.timedMetaDataSelectionKeys = ["*"]
' IMPORTANT: Failure to listen to the position and timedmetadata fields
' could result in ad impressions not being reported.
m.port = CreateObject("roMessagePort")
m.top.videoNode.observeField("position", m.port)
m.top.videoNode.observeField("timedMetaData", m.port)
m.top.videoNode.observeField("timedMetaData2", m.port)
m.top.videoNode.observeField("state", m.port)
while True
msg = wait(1000, m.port)
if m.top.videoNode = invalid
exit while
end if
m.streamManager.onMessage(msg)
currentTime = m.top.videoNode.position
if currentTime > 3 and not m.top.adPlaying
m.top.videoNode.enableTrickPlay = true
end if
end while
end sub
sub setupStreamManager()
m.streamManager.addEventListener(m.sdk.AdEvent.ERROR, errorCallback)
m.streamManager.addEventListener(m.sdk.AdEvent.START, startCallback)
m.streamManager.addEventListener(m.sdk.AdEvent.FIRST_QUARTILE, firstQuartileCallback)
m.streamManager.addEventListener(m.sdk.AdEvent.MIDPOINT, midpointCallback)
m.streamManager.addEventListener(m.sdk.AdEvent.THIRD_QUARTILE, thirdQuartileCallback)
m.streamManager.addEventListener(m.sdk.AdEvent.COMPLETE, completeCallback)
end sub
sub startCallback(ad as object)
print "Callback from SDK -- Start called - "
end sub
sub firstQuartileCallback(ad as object)
print "Callback from SDK -- First quartile called - "
end sub
sub midpointCallback(ad as object)
print "Callback from SDK -- Midpoint called - "
end sub
sub thirdQuartileCallback(ad as object)
print "Callback from SDK -- Third quartile called - "
end sub
sub completeCallback(ad as object)
print "Callback from SDK -- Complete called - "
end sub
sub errorCallback(error as object)
print "Callback from SDK -- Error called - " ; error
m.errorState = True
end sub