Native Ad Options
Ad Request Timeout (default: 60 seconds)
If no ad response is received within the specified time (in seconds) after the ad request, the existing request is invalidated and the adLoader:didFailWithError:responseInfo: method of GFPAdLoaderDelegate is called.
- Swift
- Objective-C
self.adLoader?.requestTimeoutInterval = ...
self.adLoader.requestTimeoutInterval = ...
GFPNativeAdRenderingSetting
This section covers only the most commonly used options. For the full list of all options provided by GFPNativeAdRenderingSetting, refer to Native Rendering Options.
DFP adChoicesView Position Setting
The DFP adChoiceView is rendered as an overlay. Therefore, one of the four corners where the adChoicesView will be automatically inserted must be left empty. The default position of the DFP adChoicesView is the top-right corner, and it can be configured via GFPNativeAdRenderingSetting's preferredAdChoicesViewPosition.
- Swift
- Objective-C
let renderingSetting = GFPNativeAdRenderingSetting()
renderingSetting.preferredAdChoicesViewPosition = .topRightCorner
let nativeOption = GFPAdNativeOptions()
nativeOption.renderingSetting = renderingSetting
GFPNativeAdRenderingSetting *setting = [[GFPNativeAdRenderingSetting alloc] init];
setting.preferredAdChoicesViewPosition = GFPAdChoicesViewPositionTopRightCorner;
GFPAdNativeOptions *nativeOptions = [[GFPAdNativeOptions alloc] init];
nativeOptions.renderingSetting = setting;
The Google documentation states that manually registering an adChoiceView renders it directly onto the registered view rather than as an overlay, but this does not yet work correctly. If you want the adChoiceView rendered at a position other than the top-right, this setting is required.
Using Native Ads Without a Media View
To use a native ad without a media view (for example, a native ad composed only of an icon and a title/CTA button), set hasMediaView = NO on GFPNativeAdRenderingSetting. (The default value is YES.)
If the presence of a media view in the native view does not match the GFPNativeAdRenderingSetting.hasMediaView state, an error will occur at the time of native ad rendering.
- Swift
- Objective-C
let setting = GFPNativeAdRenderingSetting()
setting.hasMediaView = false
let nativeOption = GFPAdNativeOptions()
nativeOption.renderingSetting = setting
GFPNativeAdRenderingSetting *setting = [[GFPNativeAdRenderingSetting alloc] init];
setting.hasMediaView = NO;
GFPAdNativeOptions *nativeOptions = [[GFPAdNativeOptions alloc] init];
nativeOptions.renderingSetting = setting;
Native Ad Lazy Loading
Enabling Lazy Loading
When useLazyMediaLoading is enabled in the native rendering options, the ad load callback is called first, and the image or video resources of the media view and icon view are loaded asynchronously afterwards.
- Swift
- Objective-C
self.adLoader = GFPAdLoader(unitID: "UnitId", rootViewController: self, adParam: adParam)
let nativeOption = GFPAdNativeOptions()
nativeOptions.renderingSetting.useLazyMediaLoading = true
self.adLoader?.setNativeDelegate(self, nativeOptions: nativeOption)
self.adLoader?.delegate = self
self.adLoader?.loadAd()
self.adLoader = [[GFPAdLoader alloc] initWithUnitID:self.unitID
rootViewController:self
adParam:adParam];
GFPAdNativeOptions *nativeOptions = [[GFPAdNativeOptions alloc] init];
nativeOptions.renderingSetting.useLazyMediaLoading = YES;
[self.adLoader setNativeDelegate:self nativeOptions:nativeOptions];
// Request ad
self.adLoader.delegate = self;
[self.adLoader loadAd];
With Lazy Loading, the ad load callback doesn't wait for the media to finish loading. Once the media view and icon view both load successfully, GFPNativeAdDelegate's nativeAdDidLoadMediaData(_:) is called; if either one fails, nativeAdDidFail(toLoadMediaData:) is called instead.
To help you size the media area at the ad load callback, nativeAd.mediaData may already be available, exposing preferredMediaWidth, preferredMediaHeight, and preferredHeightWithFixedWidth(_:). Image ads use the size from the ad response, and outstream native video ads derive it from the VAST media file. Treat these values as valid only when preferredMediaWidth and preferredMediaHeight are greater than 0. This early sizing is available only for standard image media and outstream native video ads.
Keep in mind that mediaData may hold only layout information at this stage. The video resource hasn't loaded yet, so access mediaData.videoController only after the main media has loaded successfully. For outstream native video, loading begins once the ad view is actually attached to the view hierarchy.
Showing a Placeholder
Show placeholders only after you set nativeAdView.nativeAd = nativeAd. By then the media view and icon view have their final size and position, so each placeholder fits its view.
- Swift
- Objective-C
func adLoader(_ unifiedAdLoader: GFPAdLoader!, didReceive nativeAd: GFPNativeAd!) {
nativeAd.delegate = self
nativeAdView.nativeAd = nativeAd
if nativeAd.mediaLoadingState == .loading {
nativeAdView.mediaView?.showPlaceholder { imageView in
imageView.image = UIImage(named: "my_media_placeholder")
imageView.contentMode = .scaleAspectFill
imageView.clipsToBounds = true
}
}
if nativeAd.iconLoadingState == .loading {
nativeAdView.showIconPlaceholder { imageView in
imageView.image = UIImage(named: "my_icon_placeholder")
imageView.contentMode = .scaleAspectFill
imageView.clipsToBounds = true
}
}
}
- (void)adLoader:(GFPAdLoader *)unifiedAdLoader didReceiveNativeAd:(GFPNativeAd *)nativeAd {
nativeAd.delegate = self;
self.nativeAdView.nativeAd = nativeAd;
if (nativeAd.mediaLoadingState == GFPNativeAdMediaLoadingStateLoading) {
[self.nativeAdView.mediaView showPlaceholderWith:^(UIImageView *imageView) {
imageView.image = [UIImage imageNamed:@"my_media_placeholder"];
imageView.contentMode = UIViewContentModeScaleAspectFill;
imageView.clipsToBounds = YES;
}];
}
if (nativeAd.iconLoadingState == GFPNativeAdMediaLoadingStateLoading) {
[self.nativeAdView showIconPlaceholderWith:^(UIImageView *imageView) {
imageView.image = [UIImage imageNamed:@"my_icon_placeholder"];
imageView.contentMode = UIViewContentModeScaleAspectFill;
imageView.clipsToBounds = YES;
}];
}
}
Removing Placeholders
Once both the media and icon load successfully, the SDK removes the placeholders for you, so you usually don't need to call removePlaceholders() yourself.
If media loading fails, the SDK leaves the placeholders in place. To show a failure state, set a new placeholder in nativeAdDidFail(toLoadMediaData:) (nativeAdDidFailToLoadMediaData:), or call removePlaceholders() yourself.
The SDK only removes placeholders added through GFPMediaView.showPlaceholder and GFPNativeAdView.showIconPlaceholder. If you added your own custom view, you're responsible for removing it.
To run a custom effect such as a fade-out before a placeholder disappears, set placeholderWillRemoveHandler. The placeholder isn't removed until you call removeHandler, so be sure to call it once your animation finishes. This handler runs both when the SDK removes a placeholder automatically on success and when you request removal yourself.
- Swift
- Objective-C
nativeAdView.placeholderWillRemoveHandler = { placeholderView, removeHandler in
UIView.animate(withDuration: 0.25, animations: {
placeholderView.alpha = 0
}, completion: { _ in
removeHandler()
})
}
self.nativeAdView.placeholderWillRemoveHandler = ^(UIImageView *placeholderView, GFPPlaceholderRemovalHandler removeHandler) {
[UIView animateWithDuration:0.25 animations:^{
placeholderView.alpha = 0;
} completion:^(BOOL finished) {
removeHandler();
}];
};
Reusable Cells
When reusing table/collection cells, we recommend calling removePlaceholders() at a reset point such as prepareForReuse so that the previous ad's placeholder does not remain.
- Swift
- Objective-C
override func prepareForReuse() {
super.prepareForReuse()
nativeAdView.removePlaceholders()
}
- (void)prepareForReuse {
[super prepareForReuse];
[self.nativeAdView removePlaceholders];
}
Async Media Loading Callbacks
Once the media view and icon view both finish loading successfully, nativeAdDidLoadMediaData(_:) is called. At that point nativeAd.mediaData is fully loaded, so you can read the final media information from it.
If either one fails, nativeAdDidFail(toLoadMediaData:) is called — once, on the first failure. The SDK doesn't clear placeholders on failure, so set a failure-state placeholder or remove it yourself.
To see which asset changed — the icon or the main media — use the didChangeMediaAssetLoadingState callback or the iconLoadingState / mediaLoadingState properties.
The SDK reports the valid impression (sc/12) to the server only after the main media loads successfully. So even if nativeAdDidFail(toLoadMediaData:) fires because the icon failed to load, the sc/12 report can still be sent as long as the main media loaded and the impression is valid.
- Swift
- Objective-C
// GFPNativeAdDelegate
func nativeAdDidLoadMediaData(_ nativeAd: GFPNativeAd) {
// The SDK removes the media/icon placeholders automatically.
let mediaData = nativeAd.mediaData
if mediaData?.mediaType == .video {
let videoController = mediaData?.videoController
// Configure videoController if needed.
}
}
func nativeAdDidFail(toLoadMediaData nativeAd: GFPNativeAd) {
if nativeAd.mediaLoadingState == .failed {
nativeAdView.mediaView?.showPlaceholder { imageView in
imageView.image = UIImage(named: "my_fallback_media_placeholder")
imageView.contentMode = .scaleAspectFill
imageView.clipsToBounds = true
}
}
if nativeAd.iconLoadingState == .failed {
nativeAdView.showIconPlaceholder { imageView in
imageView.image = UIImage(named: "my_fallback_icon_placeholder")
imageView.contentMode = .scaleAspectFill
imageView.clipsToBounds = true
}
}
}
func nativeAd(_ nativeAd: GFPNativeAd,
didChangeMediaAssetLoadingState state: GFPNativeAdMediaLoadingState,
assetType: GFPNativeAdMediaAssetType) {
switch (assetType, state) {
case (.media, .failed):
// Handle main media loading failure
break
case (.icon, .failed):
// Handle icon loading failure
break
default:
break
}
}
// GFPNativeAdDelegate
- (void)nativeAdDidLoadMediaData:(GFPNativeAd *)nativeAd {
// The SDK removes the media/icon placeholders automatically.
GFPMediaData *mediaData = nativeAd.mediaData;
if (mediaData.mediaType == GFPMediaTypeVideo) {
GFPVideoController *videoController = mediaData.videoController;
// Configure videoController if needed.
}
}
- (void)nativeAdDidFailToLoadMediaData:(GFPNativeAd *)nativeAd {
if (nativeAd.mediaLoadingState == GFPNativeAdMediaLoadingStateFailed) {
[self.nativeAdView.mediaView showPlaceholderWith:^(UIImageView *imageView) {
imageView.image = [UIImage imageNamed:@"my_fallback_media_placeholder"];
imageView.contentMode = UIViewContentModeScaleAspectFill;
imageView.clipsToBounds = YES;
}];
}
if (nativeAd.iconLoadingState == GFPNativeAdMediaLoadingStateFailed) {
[self.nativeAdView showIconPlaceholderWith:^(UIImageView *imageView) {
imageView.image = [UIImage imageNamed:@"my_fallback_icon_placeholder"];
imageView.contentMode = UIViewContentModeScaleAspectFill;
imageView.clipsToBounds = YES;
}];
}
}
- (void)nativeAd:(GFPNativeAd *)nativeAd
didChangeMediaAssetLoadingState:(GFPNativeAdMediaLoadingState)state
assetType:(GFPNativeAdMediaAssetType)assetType {
if (assetType == GFPNativeAdMediaAssetTypeMedia && state == GFPNativeAdMediaLoadingStateFailed) {
// Handle main media loading failure
} else if (assetType == GFPNativeAdMediaAssetTypeIcon && state == GFPNativeAdMediaLoadingStateFailed) {
// Handle icon loading failure
}
}
With Lazy Loading, the ad load callback and the media-loaded callback are separate. Other delegate callbacks (rendering, clicks, and so on) behave exactly as before, and the SDK sends the valid-impression (sc/12) report after the main media loads successfully.
GFPContentInfo
When applying a NativeNormal type ad as a Communication Ad, you must inject ContentInfo.
- Swift
- Objective-C
let adParam = GFPAdParam()
adParam.contentInfo = GFPContentInfo(
sourceType: "0001",
subtype: "menu",
sourceId: "30907206:7")
GFPContentInfo *contentInfo = [[GFPContentInfo alloc] initWithSourceType:@"0001" subtype:@"menu" sourceId:@"30907206:7"];
adParam.contentInfo = contentInfo;