Schedule FreeWheel ads (iOS v3)

Schedule ads with the FreeWheel Ad Manager ad client in an iOS app.


After adding the FreeWheel Ad Manager to your app and acquiring the required items listed in the Requirements section, you can schedule FreeWheel ads in your iOS app.


Requirements

PropertyDescriptionExample
mediaIdFreeWheel identifier of a particular media itemDemoVideoGroup.01
networkIdFreeWheel identifier of a network96749
profileIdFreeWheel identifier of a particular application environment96749:global-cocoa
sectionIdFreeWheel identifier of a location where the video content playsDemoSiteGroup.01
serverIdURL of FreeWheel ad serverhttp://demo.v.fwmrm.net/ad/g/1

If you do not know where to find the FreeWheel account values in the table, contact your FreeWheel account representative.



Add a single ad break for all playlist items

Use the following steps to add a single ad break to the player you added to your view. This ad break applies to all media content played in your app.

  1. Instantiate a JWAdBreak object and define its offset. When defining the offset property, choose one of the following values to schedule a pre-roll or mid-roll ad. Post-roll ads are not currently supported for FreeWheel ad implementations.

    Pre-roll
    β€’ pre: (String) Ad plays before the content

    Mid-roll
    β€’ {number}: (String) Ad plays after the specified number of seconds
    β€’ {timecode}: (String) Ad plays at a specific time, in hh:mm:ss:mmm format

    In the example below, we call the JWAdBreak object adBreak and define the offset as pre.
  2. Create a JWFreewheelConfig object that contains your FreeWheel account settings. In the example below, we call the JWFreewheelConfig object fwConf.
  3. Instantiate a JWAdConfig object and assign it to config.advertising, an instance of JWConfig.
  4. Define config.advertising.client as JWAdClientFreewheel (Obj-C) or .freewheel (Swift). This defines the ad client.
  5. Assign adBreak to the schedule property of the JWAdConfig. This adds the ad schedule to the player's config property.

@property (nonatomic) JWPlayerController *player;
@property (nonatomic, weak) IBOutlet UIView *playerContainerView;
@end

@implementation ObjCViewController


- (void)viewDidLoad {
    [super viewDidLoad];

    // Create the Ad Break
    JWAdBreak *adBreak = [JWAdBreak adBreakWithTag:@"placeholder_preroll" offset:@"pre"];

    // Create the FreeWheel Config
    JWFreewheelConfig *fwConfig = [JWFreewheelConfig new];
    fwConfig.mediaId = FREEWHEEL_MEDIA_ID;
    fwConfig.serverId = FREEWHEEL_SERVER_ID;
    fwConfig.profileId = FREEWHEEL_PROFILE_ID;
    fwConfig.sectionId = FREEWHEEL_SECTION_ID;
    fwConfig.networkId = FREEWHEEL_NETWORK_ID;

    // Create the Ad Config
    JWAdConfig *adConfig = [JWAdConfig new];
    adConfig.client = JWAdClientFreewheel;
    adConfig.freewheel = fwConfig;
    adConfig.schedule = @[adBreak];

    // Initialize the JWConfig and create the JWPlayerController
    JWConfig *config = [JWConfig configWithContentURL:CONTENT_URL];
    config.advertising = adConfig;

    self.player = [[JWPlayerController alloc] initWithConfig:config];
}

- (void)viewDidAppear {
    [super viewDidAppear];
    [self.view addSubview:self.player.view];
}
class ViewController: UIViewController {
    @IBOutlet weak var playerContainerView: UIView!
    var player: JWPlayerController?

    override func viewDidLoad() {
        super.viewDidLoad()

        // Create the Ad Break
        let adBreak = JWAdBreak(tag: "placeholder_preroll", offset: "pre")

        // Create the FreeWheel Config
        let fwConfig = JWFreewheelConfig()
        fwConfig.mediaId = FREEWHEEL_MEDIA_ID
        fwConfig.serverId = FREEWHEEL_SERVER_ID
        fwConfig.profileId = FREEWHEEL_PROFILE_ID
        fwConfig.sectionId = FREEWHEEL_SECTION_ID
        fwConfig.networkId = FREEWHEEL_NETWORK_ID

        // Create the Ad Config
        let adConfig = JWAdConfig()
        adConfig.client = .freewheel
        adConfig.freewheel = fwConfig
        adConfig.schedule = [adBreak]

        // Initialize the JWConfig and create the JWPlayerController
        let config = JWConfig(contentURL: CONTENT_URL)
        config.advertising = adConfig

        player = JWPlayerController(config: config)
    }

    override func viewDidAppear(_ animated: Bool) {
        super.viewDidAppear(animated)
        playerContainerView.addSubview(player!.view)
    }
}

You can build upon this basic implementation by adding more ad breaks.



Add multiple ad breaks for all playlist items

Use the following steps to add multiple ad breaks to the previous pre-roll example:

  1. Instantiate an additional JWAdBreak object and define its offset. When defining the offset property, choose one of the following values to schedule a pre-roll or mid-roll ad. Post-roll ads are not currently supported for FreeWheel ad implementations.

    Pre-roll
    β€’ pre: (String) Ad plays before the content

    Mid-roll
    β€’ {number}: (String) Ad plays after the specified number of seconds
    β€’ {timecode}: (String) Ad plays at a specific time, in hh:mm:ss:mmm format
  2. Add the additional AdBreak object to the schedule array.

In the code examples below, we have added several additional ad breaks.

@property (nonatomic) JWPlayerController *player;
@property (nonatomic, weak) IBOutlet UIView *playerContainerView;
@end

@implementation ObjCViewController


- (void)viewDidLoad {
    [super viewDidLoad];

    // Create the Ad Breaks
    JWAdBreak *adBreak = [JWAdBreak adBreakWithTag:@"placeholder_preroll" offset:@"pre"];
    JWAdBreak *adBreak2 = [JWAdBreak adBreakWithTag:@"placeholder_midroll" offset:@"10"];
    JWAdBreak *adBreak3 = [JWAdBreak adBreakWithTag:@"placeholder_midroll2" offset:@"00:00:15:000"];
    JWAdBreak *adBreak4 = [JWAdBreak adBreakWithTag:@"placeholder_midroll3" offset:@"25%"];
    JWAdBreak *adBreak5 = [JWAdBreak adBreakWithTag:@"placeholder_postroll" offset:@"post"];

    // Create the FreeWheel Config
    JWFreewheelConfig *fwConfig = [JWFreewheelConfig new];
    fwConfig.mediaId = FREEWHEEL_MEDIA_ID;
    fwConfig.serverId = FREEWHEEL_SERVER_ID;
    fwConfig.profileId = FREEWHEEL_PROFILE_ID;
    fwConfig.sectionId = FREEWHEEL_SECTION_ID;
    fwConfig.networkId = FREEWHEEL_NETWORK_ID;

    // Create the Ad Config
    JWAdConfig *adConfig = [JWAdConfig new];
    adConfig.client = JWAdClientFreewheel;
    adConfig.freewheel = fwConfig;
    adConfig.schedule = @[adBreak, adBreak2, adBreak3, adBreak4, adBreak5];

    // Initialize the JWConfig and create the JWPlayerController
    JWConfig *config = [JWConfig configWithContentURL:CONTENT_URL];
    config.advertising = adConfig;

    self.player = [[JWPlayerController alloc] initWithConfig:config];
}

- (void)viewDidAppear {
    [super viewDidAppear];
    [self.view addSubview:self.player.view];
}
class ViewController: UIViewController {
    @IBOutlet weak var playerContainerView: UIView!
    var player: JWPlayerController?

    override func viewDidLoad() {
        super.viewDidLoad()

        // Create the Ad Breaks
        let adBreak = JWAdBreak(tag: @"placeholder_preroll", offset: "pre")
        let adBreak2 = JWAdBreak(tag: @"placeholder_midroll", offset: "10")
        let adBreak3 = JWAdBreak(tag: @"placeholder_midroll2", offset: "00:00:15:000")
        let adBreak4 = JWAdBreak(tag: @"placeholder_midroll3", offset: "25%")
        let adBreak5 = JWAdBreak(tag: @"placeholder_postroll", offset: "post")

        // Create the FreeWheel Config
        let fwConfig = JWFreewheelConfig()
        fwConfig.mediaId = FREEWHEEL_MEDIA_ID
        fwConfig.serverId = FREEWHEEL_SERVER_ID
        fwConfig.profileId = FREEWHEEL_PROFILE_ID
        fwConfig.sectionId = FREEWHEEL_SECTION_ID
        fwConfig.networkId = FREEWHEEL_NETWORK_ID

        // Create the Ad Config
        let adConfig = JWAdConfig()
        adConfig.client = .freewheel
        adConfig.freewheel = fwConfig
        adConfig.schedule = [adBreak, adBreak2, adBreak3, adBreak4, adBreak5]

        // Initialize the JWConfig and create the JWPlayerController
        let config = JWConfig(contentURL: CONTENT_URL)
        config.advertising = adConfig

        player = JWPlayerController(config: config)
    }

    override func viewDidAppear(_ animated: Bool) {
        super.viewDidAppear(animated)
        view.addSubview(player!.view)
    }
}


Specify ad content for a specific playlist item

Use the following steps to specify advertising content for a specific playlist item. If you do not apply these steps to a playlist item, the default FreeWheel advertising content will play.

  1. For a specific JWPlaylistItem, create a JWFreewheelConfig object. In our code examples, we name this object freewheelItem1.
  2. Assign the FreeWheel media ID for the advertising content to the mediaId of the JWFreewheelConfig.
  3. Assign the mediaId to the freewheel property of the JWPlaylistitem. This associates the specific FreeWheel advertising content to the JWPlaylistitem.

@property (nonatomic) JWPlayerController *player;
@property (nonatomic, weak) IBOutlet UIView *playerContainerView;
@end

@implementation ObjCViewController


- (void)viewDidLoad {
    [super viewDidLoad];

    // Create the Ad Breaks
    // These have placeholders because FreeWheel will insert the correct tags during runtime
    JWAdBreak *adBreak = [JWAdBreak adBreakWithTag:@"placeholder_preroll" offset:@"pre"];
    JWAdBreak *adBreak2 = [JWAdBreak adBreakWithTag:@"placeholder_midroll" offset:@"15"];
    JWAdBreak *adBreak3 = [JWAdBreak adBreakWithTag:@"placeholder_postroll" offset:@"post"];

    // Create the default FreeWheel settings, and place them in the advertising config
    JWFreewheelConfig *fwConfig = [JWFreewheelConfig new];
    fwConfig.networkId = FW_NETWORK_ID;
    fwConfig.mediaId = FW_DEFAULT_MEDIA_ID;
    fwConfig.serverId = FW_SERVER_ID;
    fwConfig.profileId = FW_PROFILE_ID;
    fwConfig.sectionId = FW_SECTION_ID;

    // Create specific FreeWheel configs for the items.
    // In this example, only items 1 & 2 are changed. Item 3 will use the default.
    JWFreewheelConfig *fwConfigItem1 = [JWFreewheelConfig new];
    fwConfigItem1.mediaId = FW_MEDIA_ID;

    JWFreewheelConfig *fwConfigItem2 = [JWFreewheelConfig new];
    fwConfigItem2.mediaId = FW_MEDIA2_ID;

    // Create the playlist. item3 uses the default fwConfig.
    JWPlaylistItem *item = [JWPlaylistItem new];
    item.file = CONTENT_URL;
    item.freewheel = fwConfigItem1;

    JWPlaylistItem *item2 = [JWPlaylistItem new];
    item2.file = CONTENT2_URL;
    item2.freewheel = fwConfigItem2;

    JWPlaylistItem *item3 = [JWPlaylistItem new];
    item3.file = CONTENT3_URL;

    // Create the Ad Config
    JWAdConfig *adConfig = [JWAdConfig new];
    adConfig.client = JWAdClientFreewheel;
    adConfig.schedule = @[adBreak, adBreak2, adBreak3];
    adConfig.skipOffset = 3;
    adConfig.freewheel = fwConfig;

    // Initialize the JWConfig and create the JWPlayerController
    JWConfig *config = [JWConfig new];
    config.advertising = adConfig;
    config.playlist = @[item, item2, item3];

    self.player = [[JWPlayerController alloc] initWithConfig:config];
}

- (void)viewDidAppear {
    [super viewDidAppear];
    [self.view addSubview:self.player.view];
}
class ViewController: UIViewController {
    @IBOutlet weak var playerContainerView: UIView!
    var player: JWPlayerController?

    override func viewDidLoad() {
        super.viewDidLoad()

        // Create the Ad Breaks
        // These have placeholders because FreeWheel will insert the correct tags during runtime
        let adBreak = JWAdBreak(tag: "placeholder_preroll", offset: "pre")
        let adBreak2 = JWAdBreak(tag: "placeholder_midroll", offset: "15")
        let adBreak3 = JWAdBreak(tag: "placeholder_postroll", offset: "post")

        // Create the default FreeWheel settings, and place them in the advertising config
        let fwConfig = JWFreewheelConfig()
        fwConfig.networkId = FW_NETWORK_ID
        fwConfig.mediaId = FW_DEFAULT_MEDIA_ID
        fwConfig.serverId = FW_SERVER_ID
        fwConfig.profileId = FW_PROFILE_ID
        fwConfig.sectionId = FW_SECTION_ID

        // Create specific FreeWheel configs for the items.
        // In this example, only items 1 & 2 are changed. Item 3 will use the default.
        let fwConfigItem1 = JWFreewheelConfig()
        fwConfigItem1.mediaId = FW_MEDIA_ID

        let fwConfigItem2 = JWFreewheelConfig()
        fwConfigItem2.mediaId = FW_MEDIA2_ID

        // Create the playlist. item3 uses the default fwConfig.
        let item = JWPlaylistItem()
        item.file = CONTENT_URL
        item.freewheel = fwConfigItem1

        let item2 = JWPlaylistItem()
        item2.file = CONTENT2_URL
        item2.freewheel = fwConfigItem2

        let item3 = JWPlaylistItem()
        item3.file = CONTENT3_URL

        // Create the Ad Config
        let adConfig = JWAdConfig()
        adConfig.client = .freewheel
        adConfig.schedule = [adBreak, adBreak2, adBreak3]
        adConfig.skipOffset = 3
        adConfig.freewheel = fwConfig

        // Initialize the JWConfig and create the JWPlayerController
        let config = JWConfig()
        config.advertising = adConfig
        config.playlist = [item, item2, item3]

        player = JWPlayerController(config: config)
    }

    override func viewDidAppear(_ animated: Bool) {
        super.viewDidAppear(animated)
        view.addSubview(player!.view)
    }
}


FAQ

Why don't the ad breaks play when I build and run my project?


Check the output panel in XCode for the error displayed. One common error is "The resource could not be loaded because the App Transport Security policy requires the use of a secure connection".

You can resolve this issue by updating the info.plist file.

  1. From your project's target, open info.plist.
  2. Add a key named App Transport Security Settings as a Dictionary.
  3. Add a subkey named Allow Arbitrary Loads as a Boolean with a value set to YES.

You can also update the source code of info.plist:

<key>NSAppTransportSecurity</key>
    <dict>
        <key>NSAllowsArbitraryLoads</key>
        <true/>
    </dict>