SWIFT SDK Manual

Introduction

Voice Ads allow users to engage with ads using voice commands. While listening to music or a stream, an ad user can speak various voice commands which will be introduced to users within the ad creative. When a user says ‘skip it’, ‘next’, ‘cancel’, ‘not interested’, etc, we stop serving the current ad and play the next one if there is one scheduled.

When a user engages with the ad, we perform the requested action, e.g. open browser, playing a successive audio with ‘more details’, etc.

Actions can be ‘positive’ when users want to ‘know more’ or make a purchase or ‘negative’ when users say ‘no’ or ‘I’m not interested’.

First, you need to add "Privacy - Microphone Usage Description" flag to info.plist in order to prevent future app crashes. Then, use the code below in order to set up the microphone access request.

//
//  ViewController.swift
//  AdmanUi
//
//  Created by test name on 16/05/22.
//  Copyright В© 2016 Unisound. All rights reserved.
//
 
import AVFoundation
import UIKit
 
class DialogSampleController: UIViewController {
    
    override func viewDidLoad() {}
    
    override func didReceiveMemoryWarning() {
        super.didReceiveMemoryWarning()
    }
 
    func showRequestInfoDialog() {
        if AVAudioSession.sharedInstance().recordPermission == .granted {
            return
        }
        
        if AVAudioSession.sharedInstance().recordPermission == .denied || UserDefaults.standard.object(forKey: "admanLastMicroPermissionNotifyDate") != nil {
            if let lastNotifyDate = UserDefaults.standard.object(forKey: "admanLastMicroPermissionNotifyDate") as? Date {
                if let diff = Calendar.current.dateComponents([.day], from: lastNotifyDate, to: Date()).day {
                    if diff <= 6 {
                        return
                    }
                }
            }
            let alert = UIAlertController(title: "Microphone disabled.", message: "If you want to control advertising with your voice and even skip it please enable microphone permission in Settings.", preferredStyle: .alert)
            alert.addAction(UIAlertAction(title: "Ok", style: .default))
            present(alert, animated: false, completion: nil)
            return
        }
        let infoDialog = UIAlertController(title: "Do you want to enable Dialogue Ads?", message: "Now you can control advertising with your voice and even skip it. Do you want to try Dialogue Advertising?", preferredStyle: .alert)
        
        let noButton = UIAlertAction(title: "No", style: .default) { action in
            UserDefaults.standard.set(Date(), forKey: "admanLastMicroPermissionNotifyDate")
            UserDefaults.standard.synchronize()
        }
        let yesButton = UIAlertAction(title: "Yes", style: .default) { action in
            AVAudioSession.sharedInstance().requestRecordPermission { _ in }
        }
        infoDialog.addAction(noButton)
        infoDialog.addAction(yesButton)
        
        present(infoDialog, animated: false, completion: nil)
    }
}

Implementation

Add the following to a podfile:

pod 'Adman_swift'

Then, 'pod update' command should be used to update all the libraries from the podfile, including our SDK and 'pod update Adman_swift' should be used to update our SDK only.

The recent SDK version is 2.19.0

Integration Example

Please find the code example below. (In this example our SDK is used to run an ad every 90 seconds for illustrative purposes, for your app please implement the SDK according to your product logic.):

import AVFoundation
import UIKit
import Adman_swift
 
class ViewController: UIViewController, AdmanDelegate {
    var adman: Adman?
    var player = AVPlayer()
    
    override func viewDidLoad() {
        super.viewDidLoad()
        
        if let url = URL(string: "https://playlist.pls") {
            player = AVPlayer(url: url)
        }
        adman = Adman(siteId: 1249, region: .global, testMode: false)
        adman?.delegate = self
    }
    
    override func viewDidAppear(_ animated: Bool) {
        super.viewDidAppear(animated)
        
        player.volume = 1.0
        adman?.prepare(type: .any)
        player.play()
        
        _ = Timer(timeInterval: 90, repeats: true) { timer in
            self.adman?.reportAdEvent(eventName: "can_show")
            if self.adman?.state ?? .none == .readyForPlayback {
                let admanUI = AdmanUIBase()
                admanUI.show(rootVC: self)
                self.adman?.play()
            }
        }
    }
    
    override func didReceiveMemoryWarning() {
        super.didReceiveMemoryWarning()
    }
    
    func admanStateDidChange(sender: Adman) {
        switch (sender.state) {
        case .adChangedForPlayback, .playing, .stopped, .voiceInteractionStarted, .voiceResponsePlaying, .readyForPlayback, .voiceInteractionEnded, .fetchingInfo:
            break
        case .playbackCompleted, .error, .adNone:
            player.play()
            adman?.prepare(type: .any)
        default: break
        }
    }
}

How it works?

Here is a detailed explanation of how our Voice Ads SDK for iOS works:

Ad Request

After importing the library, you need to create a class instance to control the advertisement:

adman = Adman(siteId: 1249, region: .global, testMode: false)

In this case, 1249 is a publisher ID. We use 1249 for testing purposes only. The value for region will be different for different publishers. Please ask our representatives for your value. In this manual we are using '.global' , but for EU server you should use '.EU' . Please, do not change the server during the initial integration.

To fetch Voice ads from ad server you should use:

adman.prepare(type: .voice)

To fetch Voice Video ads from ad server you should use:

adman.prepare(type: .voiceVideo)

If you need to work with Voice ads and Audio ads simultaneously you should use:

adman.prepare(type: .any)

If an ad request is completed correctly, the state of Adman object will be changed. This occurs every time the state of Adman object is changed:

func admanStateDidChange(sender: Adman)

The above method will be called and you can check it using:

sender.state == .readyForPlayback

Here is the list of possible values of AdmanState:

If there is an ad available for playback, then playback should be started. Before starting the playback, the following method should be called:

adman.reportAdEvent(eventName: "can_show")

You need to call adman.reportAdEvent(eventName: "can_show") in any case when you're supposed to play an ad, even if you haven't received any. The method should be called at any possible ad placement in the app. This is very important and will dramatically affect the revenue. Please, see the example below for reference.

Ad Playback

First of all, advertising audio files and banner (in case of presence of a banner) will be cached. Then our SDK will call statistic pixels in order to report that ad request was made and ad was received successfully. Then, the following method must be used:

var admanUI = AdmanUIBase()
admanUI.show(rootVC: self)
adman.play()

Please note, that DefaultView will automatically start ad playback when autoPlay: true is used. So, no need to use play() method to start playback. This view is recommended for the best user experience.

On ad start AdmanState will be changed to .playing and start event will be reported by calling the corresponding statistic pixel and the Teaser audio will be delivered. At the end of Teaser audio, our SDK will activate the device microphone in order to receive a voice response from the listener. The microphone will remain active for 4 seconds. After 3 seconds, the microphone will be disabled and all the recorded material will be sent to Instreamatic recognition server. If the response was shorter than 3 seconds, our voice activity detection technology will handle it, and microphone will be turned off before 3 sec mark.

Depending on the recognition result, our SDK will perform the following actions:

  • Will deliver a second audio component;

  • Will open a link in the browser;

  • Will initiate a phone call;

  • Will deliver an AI response if user wasn’t interested in the ad subject.

In cases when a response wasn’t interpreted in the context of an actual ad, a listener will be asked to repeat the response. A listener will be able to reply once again, and then ad playback will be stopped.

In cases, when voice recognition server sensed silence or unknown noises, AI response will be played and app user will be returned to content.

In case of successful interpretation of a listener response or silence, AdmanState will be changed in the following order:

In case of an unsuccessful interpretation of a listener response, AdmanState will be changed in the following order:

First Voice Interaction

Second Voice Interaction

After the ad, listener should be returned to content and another ad should be requested.

Instance Methods Reference

Please contact us before using any additional methods!

public func prepare()
public func prepare(type: AdmanType)

These methods used to send a request to the ad server to get an ad. If succeed it starts to buffer an audio and caching of companion banner (if exists). Please see below for possible values of AdmanType

___________________________________________________________

Please, contact us before using the below methods instead of showDefaultView

Ad playback:

public func play()

Ad pause:

public func pause()

Ad resume (after the pause):

public func resume()

Ad stop:

public func stop()

___________________________________________________________

To send data for targeting, the below method can be used

adman.setSiteVariable(key: "gender", value: "M//F")
adman.setSiteVariable(key: "age", value: age)        
//or
adman.setSiteVariable(key: "gender", value: "M//F")
adman.setSiteVariable(key: "age_min", value: age_min)
adman.setSiteVariable(key: "age_max", value: age_max)

___________________________________________________________

This method must be used before prepare.

To get the SDK version, the below method can be used

public func getVersion() -> String

AdmanDelegate Reference

func admanStateDidChange(sender: Adman)

Called when adman state changed.

___________________________________________________________

func phraseRecognized(result: [String: Any])

Handles all the responses from the speech recognition server. The result displays two keys: phrase transcript and target action.

___________________________________________________________

func customVoiceIntentHandler()

Handled when there is a specific section for Voice Ads in received VAST-Document.

___________________________________________________________

func bannerTouched(urlToNavigate: String?)

Handled when listener tapped on the banner image.

___________________________________________________________

func viewClosed()

Handled when Default View is closed.

___________________________________________________________

func errorReceived(error: Error)

Handled when SDK got an error from the network or audio player.

___________________________________________________________

func log(message: String)

Use this to enable more detailed logging.

Voice Video Ads Implementation

iOS SDK supports video ads with a voice interaction.

UI layout with the displaying ad is configured automatically according to a type of ad received from the server.

The model of received ad after the parsing process has the following structure:

open class AdmanBannerWrapper: AdmanBanner {
    var crossServerAdID: String?
    var responseDelay = 0
    var responseURL: String?
    var responseLang: String?
    var redirectUrl: String?
    var sequence = 0
    var videoAd = true
}

The boolean parameter videoAd specifies if the ad has the video type and prepares the proper view and video/audio player or banner to support the received ad.

There is no need to switch manually between different types of ads (voice and video), the layout is built every time the next ad starts to play and depends on the videoAd field received from the backend.

How to test the integration?

After the integration, you will be getting unlimited Voice Ads for all your ad requests. Please make sure that the ad is reacting to your commands in the way it's expected. Test for Positive, Negative, and Swear words (if needed), etc.

How to send bug reports?

Please send all the reports by mail to support@instreamatic.com.

In case of unusual behavior (wrong responses, ad skips, etc), please send your idfa along with the incident description. So we will be able to analyze what happened. The good practice is to collect some incidents and send them all in one mail instead of sending them one my one.

In case of a crash, please send the crash log/report to inspect.

Please see our FAQ Page below for frequently asked questions

Why SDK?

Your decision to make Instreamatic Dialogue Ads available on your native mobile apps will provide a highly valuable and unique audio communication capability that makes audio ads “smart”. These ads are driven by Voice AI and allow the listener to respond to various scenarios with voice commands that drive target actions.

The Instreamatic SDK is the most simple and hassle-free way to integrate Dialogue ads to your app. There will be no need for complex coding or fine-tuning, just integrate our SDK by following this short manual and you are ready to go. The whole installation should only take an hour or so for a qualified tech professional and we will support your installation all through the process.

Is it safe?

Yes, our SDK is completely safe for your app and your users. Upon your request, we will share our tech specifications, so you can easily check for yourself that our SDK is completely safe for using it in your apps. You will have the full support from us during the integration process and even afterwards. Our SDK was tested on all Apple devices available in the market, so the possibility of a crash has been eliminated. You can implement in a test environment first to review with your QA team to become absolutely comfortable and again, we will support you through the entire process.

What kind of support can I expect?

Our support team is available by email during business hours on weekdays in most time zones. We also provide detailed installation manuals that provide clear instructions and answer most all questions. We will also answer the questions during the initial integration. Please note, that you should provide all the information regarding the issues during the integration if you need support from our side.

Please see our FAQ Page below for frequently asked questions

What to do if I do not want to use SDK?

You can contact your account manager or support team in order to get tech specifications of the protocol we are using. With our documentation, you will be able to build your own integration, but please keep in mind that you will need to perform some complex coding in order to build the integration. We will still provide support if you decide to take this option.

Feel free to contact our support at support@instreamatic.com

Last updated