Skip to content

NativeAds(WindMillNativeAdsManager)

ToBid Demo

  • Native ads are divided into Origin ads and template ads, but template ads will return template ads only when the third-party SDK supports it. The SDK provides data binding for in-feed ads and reporting of click events

  • Origin ad: aggregate the materials returned by the SDK, and the developer will render and display the subviews on the returned WindMillNativeAdView type view.

  • Template ad: Aggregation SDK directly returns the rendered ad to WindMillNativeAdView, and the developer can display it directly.

  • 原生广告分为自渲染广告和模板广告,但是模板广告只有当三方SDK支持时才会返回模板广告。SDK 提供信息流广告的数据绑定、点击事件的上报

  • 自渲染广告:聚合SDK返回物料,由开发者在返回的WindMillNativeAdView类型的view上进行子视图的自行渲染和展示。

  • 模板广告:聚合SDK直接返回渲染好的广告WindMillNativeAdView,开发者直接展示即可。

1. Native advertising management class -WindMillNativeAdsManager(原生广告管理类)

In the SDK, you only need to use WindMillNativeAdsManager to get information feed ads. WindMillNativeAdsManager supports multi-advertisement loading, and can return multiple advertisements once loaded.

在SDK里只需要使用 WindMillNativeAdsManager 就可以获取信息流广告。WindMillNativeAdsManager支持多广告加载,可以一次加载返回多个广告

** Note: When the height of adSize is 0, the template will be automatically updated to the appropriate height after render success **

注意:adSize高度为0时,模版渲染render success后自动更新到合适的高度

objective-c
@interface WindMillNativeAdsManager : NSObject

@property (nonatomic, weak) id<WindMillNativeAdsManagerDelegate> delegate;

@property (nonatomic, strong, readonly) NSString *placementId;

/*
* Mandatory parameter, when it is empty, the aggregation will be set to width=screen.bouces.size.width; height=0 by default
* Pangolin height: 0 adaptive
* Tencent: height will be automatically updated to the appropriate height after render success
*/
@property (nonatomic, assign, readwrite) CGSize adSize;

- (instancetype)initWithRequest:(WindMillAdRequest *)request;

/**
It is recommended to request no more than 3 ads.
*/
- (void)loadAdDataWithCount:(NSInteger)count;

/**
Get all ads when call methord: nativeAdsManagerSuccessToLoad
*/
- (NSArray<WindMillNativeAd *> *)getAllNativeAds;
/**
 填充后可调用, 返回广告缓存池内所有信息
*/
- (NSArray<WindMillAdInfo *> *)getCacheAdInfoList;

@end

2. Native advertising class-WindMillNativeAdView(原生广告类)

WindMillNativeAdView: After requesting the ad model returned by the native ad, after creating the WindMillNativeAdView, use refreshData: to render

WindMillNativeAdView:为请求原生广告返回的广告模型后,创建WindMillNativeAdView后,使用refreshData:渲染

  • Self-rendering advertisement (feedADMode != WindMillFeedADModeNativeExpress) The developer lays out WindMillNativeAdView according to the components provided by WindMillNativeAdView and the material information provided by WindMillNativeAd.

  • Template advertisement ( feedADMode = WindMillFeedADModeNativeExpress) Developers can directly add ABUNativeAdView to the parent view for display.

  • 自渲染广告(feedADMode != WindMillFeedADModeNativeExpress) 开发者根据WindMillNativeAdView提供的组件和WindMillNativeAd提供的物料信息对WindMillNativeAdView进行布局。

  • 模板广告(feedADMode = WindMillFeedADModeNativeExpress) 开发者可直接将ABUNativeAdView添加到父视图上进行展示。

** Note: The current layout mode supports: frame layout mode and automatic layout mode **

objective-c
@interface WindMillNativeAdView : UIView

/// 广告数据对象
@property (nonatomic, strong, readonly) WindMillNativeAd *nativeAd;

/// 当前播放广告的广告信息
@property (nonatomic, strong, readonly) WindMillAdInfo *adInfo;

/// 广告代理对象
@property (nonatomic, weak) id<WindMillNativeAdViewDelegate> delegate;

/// 广告点击弹出新页面所依赖的ViewController
@property (nonatomic, weak) UIViewController *viewController;

/// 视频组件
@property (nonatomic, strong, readonly) UIView *mediaView;

/// 广告平台logo组件
@property (nonatomic, strong, readonly) UIView *logoView;

/// dislike组件
@property (nonatomic, strong, readonly) UIButton *dislikeButton;

/// 单图广告对应的图片组件
@property (nonatomic, strong, readonly) UIImageView *mainImageView;

/// 摇一摇组件 [Optional] [仅支持百度]
/// 因为是懒加载方式,需要在refreshData之后确认渲染渠道后才会创建对应的摇一摇组件
/// 组件高度需要大于80pt。摇一摇文案内容为:摇动手机 了解更多 如果组件宽度不够,则会自动将宽度适配文字长度。
@property (nonatomic, strong, readonly) WindMillNativeAdShakeView *shakeView;

/// 3图广告时对应的ImageView组件list
@property (nonatomic, strong, readonly) NSArray<UIImageView *> *imageViewList;

/// 刷新广告数据
/// @param nativeAd 广告模型数据
/// @warning 每次获取物料信息后需要刷新调用refreshData:方法
- (void)refreshData:(WindMillNativeAd *)nativeAd;

/**
 刷新media视图frame,百度渠道
 */
- (void)mediaViewResize;

/**
 设置media视图frame,需要在refreshData之后调用,美数渠道
 */
- (void)setMediaViewSize:(CGSize)size;

/// 绑定点击的View
/// @param clickableViews 需要注册点击View的集合
- (void)setClickableViews:(NSArray<UIView *> *)clickableViews;

/// 设置占位图
/// @param placeholderImage 占位图UIImage *
- (void)setPlaceholderImage:(UIImage *)placeholderImage;

/// 注销数据对象
/// @warning 在 tableView、collectionView 等场景需要复用 WindNativeAdView 时,需要在合适的时机,例如 cell 的 prepareForReuse 方法内执行 unregisterDataObject 方法,将广告对象与 WindNativeAdView 解绑
- (void)unregisterDataObject;

@end

3. Origin advertising material information(自渲染广告物料信息)

  1. After obtaining the relevant advertising information assignment in the material loading success method, you need to call setClickableViews to register the View bound to the click and refresh the data source refreshData :. (在物料加载成功方法里获取相关广告信息赋值后,需调用 setClickableViews注册绑定点击的View并刷新数据源refreshData:。)
  2. After each acquisition of material information, it is necessary to refresh and call refreshData: method (每次获取物料信息后需要刷新调用refreshData:方法)
objective-c
@interface WindMillNativeAd : NSObject

/// Typed access to the ad title.
@property (nonatomic, copy, readonly) NSString *title;

/// Typed access to the body text, usually a longer description of the ad.
@property (nonatomic, copy, readonly) NSString *desc;

/// Typed access to the ad icon.
@property (nonatomic, copy, readonly) NSString *iconUrl;

/// 图片URL列表 【Optional,可能位nil】
/// 大图:列表中只有一个URL
/// 三图:列表中有3个URL
@property (nonatomic, strong) NSArray *imageUrlList;

/// 渠道ID
@property (nonatomic, assign) WindMillAdn networkId;

/// Typed access to the call to action phrase of the ad.
@property (nonatomic, copy, readonly) NSString *callToAction;

/// Typed access to the ad star rating.
@property (nonatomic, assign, readonly) double rating;

/// WindMillFeedADModeNativeExpress为模版渲染,此时其它属性都为nil
@property (nonatomic, assign, readonly) WindMillFeedADMode feedADMode;

@end

4. Callback monitoring

4.1 WindMillNativeAdsManagerDelegate

callbackmeaningscenarios
nativeAdsManagerSuccessToLoad:Advertisement loaded successfullyWhen the load is successful identification / self-rendering display conditions / loading data statistics
nativeAdsManager: didFailWithErrorAd loading failedReloading conditions/loading statistics/troubleshooting
回调含义使用场景
nativeAdsManagerSuccessToLoad:广告加载成功当次加载成功标识/自渲染可展示条件/加载数据统计
nativeAdsManager: didFailWithError广告加载失败重新加载条件/加载数据统计/问题排查
objective-c
@protocol WindMillNativeAdsManagerDelegate

@optional

- (void)nativeAdsManagerSuccessToLoad:(WindMillNativeAdsManager *)adsManager;

- (void)nativeAdsManager:(WindMillNativeAdsManager *)adsManager didFailWithError:(NSError *)error;

@end

4.2 WindMillNativeAdViewDelegate

callbackmeaningscenarios
nativeExpressAdViewRenderSuccess:The template ad is rendered successfullyThe native template ad is rendered successfully, and the nativeExpressAdView.size.height is dynamically updated according to the size.width (only for template rendering)
nativeExpressAdViewRenderFail: error:Raw template ad rendering failedNative template ad rendering failed (only for template rendering)
nativeAdViewWillExpose:Ad exposure callbackDisplay statistics
nativeAdViewDidClick:Ad click callbackClick statistics
nativeAdDetailViewClosed:Ad details page closed callbackStatistics
nativeAdDetailViewWillPresentScreen:Callback when the ad details page will be displayedStatistics
nativeAdView: playerStatusChanged:Video ad playback status change callbackStatistics
nativeAdView: dislikeWithReasonClick dislike callback The developer needs to remove the view in this callback, otherwise, the user clicks the fork to be invalidThe user clicks to close the ad/remove the ad view/statistics
回调含义使用场景
nativeExpressAdViewRenderSuccess:模版广告渲染成功原生模板广告渲染成功, 此时的 nativeExpressAdView.size.height 根据 size.width 完成了动态更新
(只针对模版渲染)
nativeExpressAdViewRenderFail: error:生模板广告渲染失败原生模板广告渲染失败
(只针对模版渲染)
nativeAdViewWillExpose:广告曝光回调展示数据统计
nativeAdViewDidClick:广告点击回调点击数据统计
nativeAdDetailViewClosed:广告详情页关闭回调数据统计
nativeAdDetailViewWillPresentScreen:广告详情页面即将展示回调数据统计
nativeAdView: playerStatusChanged:视频广告播放状态更改回调数据统计
nativeAdView: dislikeWithReason点击dislike回调 开发者需要在这个回调中移除视图,否则,会出现用户点击叉无效的情况用户点击关闭广告/广告视图移除/数据统计
objective-c
@protocol WindMillNativeAdViewDelegate <NSObject>

@optional
/**
* The native template ad is rendered successfully, and the nativeExpressAdView.size.height is dynamically updated according to the size.width.
* (only for template rendering)
*/
- (void)nativeExpressAdViewRenderSuccess:(WindMillNativeAdView *)nativeExpressAdView;

/**
* Native template ad rendering failed
* (only for template rendering)
*/
- (void)nativeExpressAdViewRenderFail:(WindMillNativeAdView *)nativeExpressAdView error:(NSError *)error;


/**
Ad exposure callback

@param nativeAdView instance of WindMillNativeAdView
*/
- (void)nativeAdViewWillExpose:(WindMillNativeAdView *)nativeAdView;


/**
Ad click callback

@param nativeAdView instance of WindMillNativeAdView
*/
- (void)nativeAdViewDidClick:(WindMillNativeAdView *)nativeAdView;


/**
Ad details page close callback

@param nativeAdView instance of WindMillNativeAdView
*/
- (void)nativeAdDetailViewClosed:(WindMillNativeAdView *)nativeAdView;


/**
The ad details page is about to display a callback

@param nativeAdView instance of WindMillNativeAdView
*/
- (void)nativeAdDetailViewWillPresentScreen:(WindMillNativeAdView *)nativeAdView;


/**
Video ad playback state change callback

@param nativeAdView instance of WindMillNativeAdView
@param status video ad playback status
@param userInfo video ad information
*/
- (void)nativeAdView:(WindMillNativeAdView *)nativeAdView playerStatusChanged:(WindMillMediaPlayerStatus)status userInfo:(NSDictionary *)userInfo;


/**
Click dislike callback
The developer needs to remove the view in this callback, otherwise, it will be invalid for the user to click the fork
 
@param filterWords : select the reason for dislike
*/
- (void)nativeAdView:(WindMillNativeAdView *)nativeAdView dislikeWithReason:(NSArray<WindDislikeWords *> *)filterWords;

@end

5. Origin ad example(自渲染)

Ad loading and acquisition of self-rendering materials: 广告加载和自渲染物料的获取:

objective-c
// Ad loading
- (void)loadNativeAds {
  WindMillAdRequest *request = [WindMillAdRequest request];
  request.placementId = @"";
  request.userId = @"user_id"
  WindMillNativeAdsManager *nativeAdManager = [[WindMillNativeAdsManager alloc] initWithRequest:request];
  nativeAdManager.delegate = self;
  nativeAdManager.adSize = CGSizeMake(320, 0);
  [nativeAdManager loadAdDataWithCount:3];
  }
@end

The supporting Demo mainly uses the refreshUIWithModel: method for specific rendering layout:

配套Demo主要使用refreshUIWithModel: 方法来进行具体的渲染布局:

objective-c

- (void)refreshUIWithModel:(WindMillNativeAd *)model  {
  WindMillNativeAdView *adView = [WindMillNativeAdView new];
  adView.delegate = self;
  [adView refreshData:nativeAd];
  adView.viewController = self;
  [self.view addSubView:adView];
  self.adView = adView;
  [self renderAdWithLargeImg:model adView:adView];
  }

+ (void)renderAdWithLargeImg:(WindMillNativeAd *)nativeAd adView:(NativeAdCustomView *)adView{
  CGFloat width = CGRectGetWidth(UIScreen.mainScreen.bounds);
  CGFloat contentWidth = (width - 2 * margin);
  CGFloat imageHeight = 170;
  [adView.mainImageView mas_remakeConstraints:^(MASConstraintMaker *make) {
  make.top.equalTo(adView.mainImageView.superview).offset(padding.top);
  make.left.equalTo(adView.mainImageView.superview).offset(padding.left);
  make.right.equalTo(adView.mainImageView.superview).offset(-padding.right);
  make.height.mas_equalTo(imageHeight);
  }];
  
  CGSize iconSize = CGSizeMake(60, 60);
  NSURL *iconUrl = [NSURL URLWithString:nativeAd.iconUrl];
  adView.iconImageView.layer.masksToBounds = YES;
  adView.iconImageView.layer.cornerRadius = 10;
  [adView.iconImageView sd_setImageWithURL:iconUrl];
  
  [adView.iconImageView mas_remakeConstraints:^(MASConstraintMaker *make) {
  make.size.mas_equalTo(iconSize);
  make.top.equalTo(adView.mainImageView.mas_bottom).offset(10);
  make.left.equalTo(adView.iconImageView.superview).offset(padding.left);
  }];
  
  NSAttributedString *attributedText = [FeedStyleHelper titleAttributeText:nativeAd.title];
  adView.titleLabel.attributedText = attributedText;
  adView.titleLabel.lineBreakMode = NSLineBreakByTruncatingTail;
  
  [adView.titleLabel mas_remakeConstraints:^(MASConstraintMaker *make) {
  make.top.equalTo(adView.iconImageView.mas_top).offset(0);
  make.left.equalTo(adView.iconImageView.mas_right).offset(padding.left);
  make.right.equalTo(adView.CTAButton.mas_left).offset(-padding.right);
  make.height.equalTo(@30);
  }];
  
  [adView.CTAButton setTitle:nativeAd.callToAction forState:UIControlStateNormal];
  [adView.CTAButton mas_remakeConstraints:^(MASConstraintMaker *make) {
  make.top.equalTo(adView.iconImageView.mas_top).offset(0);
  make.right.equalTo(adView.CTAButton.superview).offset(-padding.right);
  make.width.equalTo(@80);
  make.height.equalTo(@30);
  }];
  
  NSAttributedString *attributedDescText = [FeedStyleHelper titleAttributeText:nativeAd.desc];
  CGSize descSize = [attributedDescText boundingRectWithSize:CGSizeMake(contentWidth, 0) options:NSStringDrawingUsesLineFragmentOrigin | NSStringDrawingUsesFontLeading context:0].size;
  adView.descLabel.attributedText = attributedDescText;
  adView.descLabel.numberOfLines = 0;
  adView.descLabel.textColor = UIColor.blackColor;
  [adView.descLabel mas_remakeConstraints:^(MASConstraintMaker *make) {
  make.top.equalTo(adView.iconImageView.mas_bottom).offset(10);
  make.left.equalTo(adView.descLabel.superview).offset(padding.left);
  make.right.equalTo(adView.descLabel.superview).offset(-padding.right);
  make.height.equalTo(@(descSize.height));
  }];
  
  [adView.dislikeButton mas_remakeConstraints:^(MASConstraintMaker *make) {
  make.bottom.equalTo(adView).offset(-10);
  make.right.equalTo(adView).offset(-10);
  make.width.mas_equalTo(15);
  make.height.mas_equalTo(15);
  }];
  
  UIView *logoView = (UIView *)adView.logoView;
  [logoView mas_remakeConstraints:^(MASConstraintMaker *make) {
  make.bottom.equalTo(logoView.superview).offset(-10);
  make.left.equalTo(logoView.superview).offset(10);
  make.width.equalTo(@(70));
  make.height.equalTo(@(20));
  }];
  [adView mas_remakeConstraints:^(MASConstraintMaker *make) {
  make.top.left.bottom.right.equalTo(adView.superview).offset(0);
  make.width.mas_equalTo(UIScreen.mainScreen.bounds.size.width);
  make.height.mas_equalTo(imageHeight + descSize.height + iconSize.height + 80);
  }];
  
  [adView setClickableViews:@[adView.CTAButton, adView.mainImageView, adView.iconImageView]];
  }

Note: Demo is for large image rendering examples. It should be noted that video type rendering requires the use of mediaView

注意:Demo针对大图渲染示例,需要注意的是视频类型的渲染需要使用mediaView

6 Precautions for ad preloading(广告预加载注意事项)

  • 需要在变现平台开启预加载功能
    You need to enable the preloading function on the monetization platform

  • 当广告开始播放时,ToBid SDK会自动执行下一条广告加载逻辑,且自动加载广告的结果不会立即给开发者回调加载成功/加载失败的回调,开发者需要再次调用loadAdData接口,若自动加载的广告有填充,则该次加载会立即回调开发者广告加载成功回调。
    When the ad starts playing, ToBid SDK will automatically execute the next ad loading logic, and the result of automatically loading the ad will not immediately call back the developer's loading success/failure callback. The developer needs to call the loadAdData interface again. If the automatically loaded ad is filled, the loading will immediately call back the developer's ad loading success callback.

  • WindMillNativeAdsManager每个广告位ID创建一个实例对象,多个实例对象之间的预加载逻辑互不干扰。
    WindMillNativeAdsManager creates an instance object for each ad slot ID, and the preloading logic between multiple instance objects does not interfere with each other.

objective-c
WindMillAdRequest *request = [WindMillAdRequest request];
request.placementId = @"";
request.userId = @"user_id"
//nativeAdManager全局对象,每个广告位ID创建一个实例
if (self.nativeAdManager == nil) {
    self.nativeAdManager = [[WindMillNativeAdsManager alloc] initWithRequest:request];
}
self.nativeAdManager.delegate = self;
self.nativeAdManager.adSize = CGSizeMake(320, 0);
[self.nativeAdManager loadAdDataWithCount:1];

7. Template example(模板渲染示例)

The loading of the template example is the same as that of the self-rendering ad, the difference is that the rendering is simpler, and you don’t need to care about the title, description, icon, large image, video and other elements

模板示例的加载和自渲染广告加载相同,不同的是在渲染上更简单,不需要关心标题、描述、icon、大图、视频等元素

objective-c
- (void)refreshUIWithModel:(WindMillNativeAd *)model  {
  WindMillNativeAdView *adView = [WindMillNativeAdView new];
  adView.delegate = self;//set delegate before refreshData
  [adView refreshData:nativeAd];
  adView.viewController = self;//set viewController after refreshData
  [self.view addSubView:adView];
  self.adView = adView;
    [adView mas_remakeConstraints:^(MASConstraintMaker *make) {
        make.top.left.bottom.equalTo(adView.superview).offset(0);
        make.width.mas_equalTo(adView.frame.size.width);
        make.height.mas_equalTo(adView.frame.size.height);

  }];

}

** Note: After the nativeExpressAdViewRenderSuccess callback of the ad rendered by the template, adView.size.height will be automatically adjusted to a suitable value according to the width **

注意:模版渲染的广告在nativeExpressAdViewRenderSuccess回调后,adView.size.height会根据width自动调整到适合的值

7. Special Instructions (特别说明)

When loading an ad, both template rendering and self-rendering use WindMillNativeAdsManager to load the ad. In the ad loading success callback, you can get all available ad models through getAllNativeAds, and use the feedADMode in the model to distinguish whether it is template rendering or non-template rendering.

The template rendering layout is relatively simple, only the entire WindMillNativeAdView is needed for the layout When the height of adSize passed in for template rendering is 0, the height of the view needs to be adjusted in the callback of successful rendering Origin ad needs the most title, description, icon, video/big picture, cta button to make a custom layout

加载广告时,模版渲染和自渲染统一使用WindMillNativeAdsManager加载广告,在广告加载成功回调中,可以通过getAllNativeAds获取所有可用广告模型,通过模型中的feedADMode区分是模版渲染还是非模版渲染。

模版渲染布局相对简单,只需要最整个WindMillNativeAdView做布局即可

模版渲染传入adSize的高度为0时,需要在渲染成功的回调调整view的高度

自渲染需要最标题、描述、icon、视频/大图、cta按钮做自定义布局