Get Started

Prerequisites

  • Xcode 13 or higher

This guide describes how to invoke the PAL SDK to receive a nonce and monitor playback events. To follow along with the completed guide, download the PAL tvOS sample application.

Add the PAL SDK to your project

Install the PAL SDK using Swift Package Manager

The Programmatic Access Library SDK supports Swift Package Manager starting in version 2.5.3. Follow the steps below to import the Swift package.

  1. In Xcode, install the IMA SDK Swift Package by navigating to File > Add Packages....

  2. In the prompt that appears, search for the IMA SDK Swift Package GitHub repository:

    https://github.com/googleads/swift-package-manager-google-programmatic-access-library-tvos
    
  3. Select the version of the PAL SDK Swift Package you want to use. For new projects, we recommend using the Up to Next Major Version.

Once you're finished, Xcode resolves your package dependencies and downloads them in the background. For more details on how to add package dependencies, see Apple's article.

Manually download and install the PAL SDK

If you don't want to use Swift Package Manager, you can download the PAL SDK and manually add it to your project.

  1. Download and extract the PAL SDK for iOS
  2. Follow the Apple Developer Guide to incorporate the framework in your project.

Generate a nonce

A "nonce" is a single encrypted string generated by PAL using the PALNonceLoader. The PAL SDK requires each new stream request to be accompanied by a newly generated nonce. However, nonces can be reused for multiple ad requests within the same stream.

All of the code snippets below are modifications to ViewController.m in the PAL tvOS sample application.

To request a nonce, start by importing the PAL library:

@import ProgrammaticAccessLibrary;

Next, create an instance of the PALNonceLoader, and add stubs for the two delegate methods:

@interface ViewController () <PALNonceLoaderDelegate>
// The nonce loader to use for nonce requests.
@property(nonatomic) PALNonceLoader *nonceLoader;
// The view in which a video would play.
// In this sample, it is mocked for simplification.
@property(nonatomic, weak) IBOutlet UIView *videoView;
@end
...
- (void) viewDidLoad {
  [super viewDidLoad];
  // The default value for 'allowStorage' and
  // 'directedForChildOrUnknownAge' is 'NO', but should be updated once the
  // appropriate consent has been gathered. Publishers should either
  // integrate with a CMP or use a different method to handle storage consent.
  PALSettings *settings = [[PALSettings alloc] init];
  settings.allowStorage = YES;
  settings.directedForChildOrUnknownAge = NO;

  self.nonceLoader = [[PALNonceLoader alloc] initWithSettings:settings];
  self.nonceLoader.delegate = self;
}

#pragma mark - PALNonceLoaderDelegate methods

- (void)nonceLoader:(PALNonceLoader *)nonceLoader
            withRequest:(PALNonceRequest *)request
    didLoadNonceManager:(PALNonceManager *)nonceManager {
}

- (void)nonceLoader:(PALNonceLoader *)nonceLoader
         withRequest:(PALNonceRequest *)request
    didFailWithError:(NSError *)error {
}

Then, initiate a nonce request, populate its properties, and use it to initialize a nonce manager:

@interface ViewController () <PALNonceLoaderDelegate>
// The nonce loader to use for nonce requests.
@property(nonatomic) PALNonceLoader *nonceLoader;
// The nonce manager result from the last successful nonce request.
@property(nonatomic) PALNonceManager *nonceManager;
// The view in which a video would play. In this sample, it is mocked for
// simplification.
@property(nonatomic, weak) IBOutlet UIView *videoView;
@end

...

- (void)viewDidLoad {
  ...
  self.nonceLoader.delegate = self;
  [self requestNonceManager];
}

...

#pragma mark - UI Callback methods

/**
 * Requests a new nonce manager with a request containing arbitrary test values
 * like a (sane) user might supply. Displays the nonce or error on success. This
 * should be called once per stream.
 *
 * The PALNonceRequest parameters set here are example parameters.
 * You should set your parameters based on your own app characteristics.
 */
- (void)requestNonceManager {
  PALNonceRequest *request = [[PALNonceRequest alloc] init];
  request.continuousPlayback = PALFlagOff;
  request.descriptionURL = [NSURL URLWithString:@"https://example.com/desc?key=val"];
  request.iconsSupported = YES;
  request.playerType = @"AwesomePlayer";
  request.playerVersion = @"4.2.1";
  request.PPID = @"123987456";
  request.sessionID = @"Sample SID";
  // Sample API framework integer. See reference docs for more details.
  NSInteger SampleAPIFramework = 501;
  request.supportedApiFrameworks = [NSMutableSet setWithArray:@[ SampleAPIFramework ]];
  request.videoPlayerHeight = 480;
  request.videoPlayerWidth = 640;
  request.willAdAutoPlay = PALFlagOn;
  request.willAdPlayMuted = PALFlagOff;

  if (self.nonceManager) {
    // Detach the old nonce manager's gesture recognizer before destroying it.
    [self.videoView removeGestureRecognizer:self.nonceManager.gestureRecognizer];
    self.nonceManager = nil;
  }
  [self.nonceLoader loadNonceManagerWithRequest:request];
}

Lastly, populate the nonce loader delegates to log generated nonces:

#pragma mark - PALNonceLoaderDelegate methods

- (void)nonceLoader:(PALNonceLoader *)nonceLoader
            withRequest:(PALNonceRequest *)request
    didLoadNonceManager:(PALNonceManager *)nonceManager {
  NSLog(@"Programmatic access nonce: %@", nonceManager.nonce);
  // Capture the created nonce manager and attach its gesture recognizer to the video view.
  self.nonceManager = nonceManager;
  [self.videoView addGestureRecognizer:self.nonceManager.gestureRecognizer];
}

- (void)nonceLoader:(PALNonceLoader *)nonceLoader
         withRequest:(PALNonceRequest *)request
    didFailWithError:(NSError *)error {
  NSLog(@"Error generating programmatic access nonce: %@", error);
}

When making your direct VAST call (DVC), set your nonce as the value on the givn parameter. The nonce is URL safe—you don't need to URL-encode it.

Lastly, you need to add methods to handle sending content playback session information and clicks to the SDK. See the following example implementing the methods sendPlaybackStart, sendPlaybackEnd, and sendAdClick:

...

// Reports the start of playback for the current content session.
- (void)sendPlaybackStart {
  [self.nonceManager sendPlaybackStart];
}

// Reports the end of playback for the current content session.
- (void)sendPlaybackEnd {
  [self.nonceManager sendPlaybackEnd];
}

// Reports an ad click for the current nonce manager, if not nil.
- (void)sendAdClick {
  [self.nonceManager sendAdClick];
}

In your implementation, sendPlaybackStart should be called on "video player start" as playback initiates for the first time, in response to either a user-initiated action (click-to-play) or an app initiated action (autoplay), sendPlaybackEnd should be called when playback ends, and sendAdClick should be called each time the viewer clicks an ad.

(Optional) Send Google Ad Manager signals through third-party ad servers

Configure the third-party ad server's request for Ad Manager. After you complete the following steps, the nonce parameter propagates from the PAL SDK, through your intermediary servers, and then to Google Ad Manager. This enables better monetization through Google Ad Manager.

Configure your third-party ad server to include the nonce in the server's request to Ad Manager. Here's an example of an ad tag configured inside of the third-party ad server:

https://pubads.serverside.net/gampad/ads?givn=%%custom_key_for_google_nonce%%&...

For more details, see the Google Ad Manager Server-side implementation guide.

Ad Manager looks for givn= to identify the nonce value. The third-party ad server needs to support some macro of its own, such as %%custom_key_for_google_nonce%%, and replace it with the nonce query parameter you provided in the previous step. More information on how to accomplish this should be available in the third-party ad server's documentation.