菜单

原生广告

1. 主要开发工作说明

1. 创建一个自定义Native Adapter类,可继承NSObject,并遵循ATAdAdapter协议,建议以NativeAdapter结尾,类名需要配置到Taku后台的自定义广告平台;

2. 自定义adapter类必须实现方法说明如下:

•当SDK需要请求到配置自定义广告源时,会调用方法initWithNetworkCustomInfo:实例化adapter对象;

•请求自定义广告源广告会触发adapter的loadADWithInfo:方法调用;

•需要设置rendererClass,继承ATNativeRenderer,当广告渲染出来的时候,需要调用这个方法对关键要素按照广告平台SDK进行转换

具体方法说明如下:

抽象方法参数说明返回值作用是否必须
-(instancetype) initWithNetworkCustomInfo:(NSDictionary* )serverInfo localInfo:(NSDictionary* )localInfoserverInfo: 服务端配置的参数字典
localInfo: 本次加载传入的参数字典
instancetype用于初始化自定义adapter
-(void) loadADWithInfo:(NSDictionary* )serverInfo localInfo:(NSDictionary* )localInfo completion:(void (^)(NSArrayserverInfo: 服务端配置的参数字典
localInfo: 本次加载传入的参数字典
void实现展示自定义广告平台加载广告的逻辑
+(Class) rendererClass-自定义Renderer类用于返回自定义Renderer类

3. 回调方法说明如下: 需要自定义实现一个xxxCustomEvent类,继承ATNativeCustomEvent类,并通过这个类添加自定义广告平台对应的回调代理,当广告平台有回调时,将对应事件调用ATNativeCustomEvent的方法回传给Taku SDK。

具体回调方法说明如下:

回调方法参数说明说明
-(void) trackNativeAdLoaded:(NSDictionary* )assetsassets:原生广告素材广告加载成功时执行回调给开发者
-(void) trackNativeAdLoadFailed:(NSError* )errorerror:错误信息广告加载失败时执行回调给开发者
-(void) trackNativeAdImpression-广告页面打开时执行回调给开发者
-(void) trackNativeAdClick-广告被点击时执行的回调给开发者
-(void) trackNativeAdClosed-广告点击关闭时执行回调给开发者


2. 具体集成说明及示例

2.1 实现广告加载的Adapter类

1. 创建一个自定义Native Adapter类,可继承NSObject,建议以NativeAdapter结尾,类名需要配置到Taku后台的自定义广告平台;

2.自定义adapter类必须实现方法如下:

•实现initWithNetworkCustomInfo:实例化adapter对象,可以在这里进行广告SDK的相关初始化;

•实现广告加载时调用的loadADWithInfo:方法,触发广告SDK的广告请求;

•需要设置rendererClass,继承ATNativeRenderer,当广告渲染出来的时候,需要调用这个方法对关键要素按照广告平台SDK进行

以下是集成示例,具体项目可参考 demo 中 CustomAdapter中 的示例代码:

创建并实现TouTiaoNativeCustomAdapter类

//TouTiaoNativeCustomAdapter.h
#import <AnyThinkNative/AnyThinkNative.h>

@interface TouTiaoNativeCustomAdapter()
@property(nonatomic, readonly) TouTiaoNativeCustomEvent *customEvent;
@end

@implementation TouTiaoNativeCustomAdapter

/// Adapter initialization method
/// - Parameters:
///   - serverInfo: Data from the server
///   - localInfo: Data from the local
-(instancetype) initWithNetworkCustomInfo:(NSDictionary*)serverInfo localInfo:(NSDictionary*)localInfo {
    self = [super init];
    if (self != nil) {
    //TODO: add some code for initialize Network SDK
    }
    return self;
}

/// Adapter sends a load request, means the ad source sends an ad load request
/// - Parameters:
///   - serverInfo: Data from the server
///   - localInfo: Data from the local
///   - completion: completion
-(void) loadADWithInfo:(NSDictionary*)serverInfo localInfo:(NSDictionary*)localInfo completion:(void (^)(NSArray *, NSError *))completion {
    _customEvent = [TouTiaoNativeCustomEvent new];
    _customEvent.isVideo = [serverInfo[@"is_video"] integerValue] == 1;
     //必须赋值
    _customEvent.requestCompletionBlock = completion;

    NSDictionary *extraInfo = localInfo;
    _customEvent.requestExtra = extraInfo;
    NSString *sizeKey = [serverInfo[@"media_size"] integerValue] > 0 ? @{@2:kATExtraNativeImageSize228_150, @1:kATExtraNativeImageSize690_388}[serverInfo[@"media_size"]] : extraInfo[kATExtraNativeImageSizeKey];
    NSInteger imgSize = [@{kATExtraNativeImageSize228_150:@9, kATExtraNativeImageSize690_388:@10}[sizeKey] integerValue];

    BUAdSlot *slot = [[NSClassFromString(@"BUAdSlot") alloc] init];
    slot.ID = serverInfo[@"slot_id"];
    slot.AdType = [@{@0:@(BUAdSlotAdTypeFeed), @1:@(BUAdSlotAdTypeDrawVideo), @2:@(BUAdSlotAdTypeBanner), @3:@(BUAdSlotAdTypeInterstitial)}[@([serverInfo[@"is_video"] integerValue])] integerValue];
    slot.isOriginAd = YES;
    slot.position = 1;
    slot.imgSize = [NSClassFromString(@"BUSize") sizeBy:imgSize];
    slot.isSupportDeepLink = YES;

    CGSize size = CGSizeMake(CGRectGetWidth([UIScreen mainScreen].bounds) - 30.0f, 200.0f);
    if ([extraInfo[kExtraInfoNativeAdSizeKey] respondsToSelector:@selector(CGSizeValue)]) { size = [extraInfo[kExtraInfoNativeAdSizeKey] CGSizeValue]; }

    _adMgr = [[BUNativeExpressAdManager alloc] initWithSlot:slot adSize:size];
    _adMgr.delegate = _customEvent;
    _adMgr.adslot = slot;
    [_adMgr loadAd:[serverInfo[@"request_num"] integerValue]];
    
}
+(Class) rendererClass {
    return [ATTTNativeRenderer class];
}

2.2 实现NativeRenderer 广告渲染的实现

Taku SDK内部针对原生广告的渲染做了一层封装,故实现自定义Adapter时,需要实现Renderer类,广告平台返回的原生参数映射到Taku内部对象。

1.实现继承ATNativeRenderer的Renderer类,参考如下:

@interface TouTiaoNativeRenderer : ATNativeRenderer
@property(nonatomic, readonly) TouTiaoNativeCustomEvent *customEvent;
@end

2. 实现renderOffer方法,可以根据广告平台的要求,做渲染之后需要的例如注册点击事件之类的功能,参考如下:

-(void) renderOffer:(ATNativeADCache *)offer {
    [super renderOffer:offer];
    _customEvent = offer.assets[kAdAssetsCustomEventKey];
    _customEvent.adView = self.ADView;
    self.ADView.customEvent = _customEvent;
    // 由于穿山甲设置广告代理需要 BUNativeExpressAdManager ,所以自定义了一个key传入到这里使用
    BUNativeExpressAdManager *nativeExpressAd = (BUNativeExpressAdManager *)offer.assets[@"tt_nativeexpress_manager"];
    nativeExpressAd.delegate = _customEvent;
    BUNativeExpressAdView *nativeFeed = offer.assets[kAdAssetsCustomObjectKey];
    nativeFeed.rootViewController = self.configuration.rootViewController;
    [nativeFeed render];
    [self.ADView addSubview:(UIView*)nativeFeed];
    nativeFeed.center = CGPointMake(CGRectGetMidX(self.ADView.bounds), CGRectGetMidY(self.ADView.bounds));
}

3. 如果广告形式存在MediaView,则需要实现createMediaView,以返回mediaview对象给到Taku,参考如下:

-(UIView*)createMediaView {
    ATVideoView *videoView = [[ATVideoView alloc] initWithFrame:self.ADView.bounds URL:nil];
    videoView.autoPlay = ((ATNativeADCache*)self.ADView.nativeAd).placementModel.wifiAutoSwitch;
    return videoView;
}

4.其他原生广告功能可选重写的方法,请前往 Demo 中查看。

2.3 实现广告回调的CustomEvent类

 需要自定义实现一个xxxCustomEvent类,继承ATNativeCustomEvent类,并通过这个类添加自定义广告平台对应的回调代理,当广告平台有回调时,将对应事件调用ATNativeCustomEvent的方法回传给Taku SDK。

以下是集成示例,具体项目可参考 Demo 中 CustomAdapter中 的示例代码:

创建并实现TouTiaoNativeCustomEvent类:

以下为穿山甲Native广告回调示例:

- (void)nativeExpressAdSuccessToLoad:(BUNativeExpressAdManager *)nativeExpressAd views:(NSArray<__kindof BUNativeExpressAdView *> *)views {
    NSLog(@"TTNative::nativeExpressAdSuccessToLoad:nativeAds:");
    if (views.count) {
        NSMutableArray* assets = [NSMutableArray array];
        [views enumerateObjectsUsingBlock:^(BUNativeExpressAdView *  _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) {
            NSMutableDictionary *asset = [NSMutableDictionary dictionary];
            BUNativeExpressAdView* expressView = obj;
            [asset setValue:self forKey:kAdAssetsCustomEventKey];
            [asset setValue:expressView forKey:kATAdAssetsCustomObjectKey];
            // 原生模板广告
            [asset setValue:@(1) forKey:kATNativeADAssetsIsExpressAdKey];
            [asset setValue:@(nativeExpressAdView.frame.size.width) forKey:kATNativeADAssetsNativeExpressAdViewWidthKey];
            [asset setValue:@(nativeExpressAdView.frame.size.height) forKey:kATNativeADAssetsNativeExpressAdViewHeightKey];
            
            
            expressView.rootViewController = [UIApplication sharedApplication].keyWindow.rootViewController;
            [assets addObject:asset];
        }];
        self.requestCompletionBlock(assets, nil);
    }
}

- (void)nativeExpressAdFailToLoad:(BUNativeExpressAdManager *)nativeExpressAd error:(NSError *_Nullable)error{
    NSLog(@"%@",[NSString stringWithFormat:@"TTNative::nativeAdsManager:didFailWithError:%@", error]);
    self.requestCompletionBlock(nil, error);
}


- (void)nativeExpressAdViewRenderSuccess:(BUNativeExpressAdView *)nativeExpressAdView {
    NSLog(@"TTNative::nativeExpressAdViewRenderSuccess:");
}

- (void)nativeExpressAdViewDidClick:(BUNativeExpressAdView *)nativeExpressAdView {
    NSLog(@"TTNative::nativeAdDidClick:withView:");
    [self trackNativeAdClick];
}

- (void)nativeExpressAdView:(BUNativeExpressAdView *)nativeExpressAdView dislikeWithReason:(NSArray *)filterWords {
    NSLog(@"TTNative::nativeAd:dislikeWithReason:");
    [self trackNativeAdClosed];
}

- (void)nativeExpressAdViewPlayerDidPlayFinish:(BUNativeExpressAdView *)nativeExpressAdView error:(NSError *)error {
    NSLog(@"TTNative::nativeAd:nativeExpressAdViewPlayerDidPlayFinish:");
    [self trackNativeAdVideoEnd];
}

注:此类中,需要在回调中将广告平台返回的原生广告素材映射到Taku的对应的asset字典中,具体key的字段说明如下:

keyrequiredtypedescription
kATAdAssetsCustomEventKeyYESNSObject广告展示后,接收广告代理事件的对象
kATNativeADAssetsUnitIDKeyNONSString三方广告平台的代码位id
kATAdAssetsCustomObjectKeyYESid三方平台返回的广告对象(数据)

原生模板信息流还需要映射的key:

keyrequiredtypedescription
kATNativeADAssetsIsExpressAdKeyYESBOOL原生信息流广告的类型,模板广告必须设置
kATNativeADAssetsNativeExpressAdViewWidthKeyNONSNumber模板广告视图的宽度
kATNativeADAssetsNativeExpressAdViewHeightKeyNONSNumber模板广告视图的高度

原生自渲染信息流还需要映射的key,映射之后才能在获取到的广告offer拿到相应的值,如果不需要或者没有的值,可以不用传入,如下:

keyrequiredtypedescription
kATNativeADAssetsIsExpressAdKeyNOBOOL原生信息流广告的类型,默认为自渲染广告类型
kATNativeADAssetsMainTitleKeyNONSString广告的标题
kATNativeADAssetsMainTextKeyNONSString广告的描述
kATNativeADAssetsIconURLKeyNONSString广告的icon图片的URL地址
kATNativeADAssetsIconImageKeyNOUIImage广告的icon图片
kATNativeADAssetsImageURLKeyNONSString广告的大图片的URL地址
kATNativeADAssetsMainImageKeyNOUIImage广告的大图片
kATNativeADAssetsCTATextKeyNONSString广告的cta文案
kATNativeADAssetsRatingKeyNONSString广告的评级分
kATNativeADAssetsAdvertiserKeyNONSString广告的广告主
kATNativeADAssetsContainsVideoFlagNOBOOL是否为视频类广告
kATNativeADAssetsLogoURLKeyNONSString广告的logo图片的URL地址
kATNativeADAssetsLogoImageKeyNOUIImage广告的logo图片

如果平台没有提供image下载的方法,可以使用Taku内部封装的方法,具体参考如下:

 dispatch_group_enter(image_download_group);
        [[ATImageLoader shareLoader] loadImageWithURL:[NSURL URLWithString:nativeAd.data.icon.imageURL] completion:^(UIImage *image, NSError *error) {
            if ([image isKindOfClass:[UIImage class]]) { asset[kNativeADAssetsIconImageKey] = image; }
            dispatch_group_leave(image_download_group);
        }];


上一个
横幅广告
下一个
自定义高级配置
最近修改: 2025-09-03Powered by