Menu

Custom Native Ad Adapter

💡Tips: The class name can be customized, but it must be consistent with the custom ad platform class name configured in the backend. For example, if the adapter class name added in the backend is: DemoCustomNativeAdapter, you need to create the corresponding DemoCustomNativeAdapter.m file.

Copy
Native/
├── DemoCustomNativeAdapter.h          # Native ad adapter header file
├── DemoCustomNativeAdapter.m          # Native ad adapter implementation file
├── DemoCustomNativeDelegate.h         # Native ad delegate header file
├── DemoCustomNativeDelegate.m         # Native ad delegate implementation file
├── DemoCustomNativeObject.h           # Native ad object header file
└── DemoCustomNativeObject.m           # Native ad object implementation file

2. Required Override Methods

You need to inherit from DemoCustomBaseAdapter and override the relevant methods:

  • When developers call the ad loading API, the custom Adapter's loadADWithArgument: method will be called
  • When developers call the ad registration API, the custom native ad object's registerClickableViews:withContainer:registerArgument: method will be called
  • When developers call the ad configuration API, the custom native ad object's setNativeADConfiguration: method will be called
Method Parameter Description Purpose
- (void)loadADWithArgument:(ATAdMediationArgument *)argument argument: Contains parameters from server and local configuration Used to get server and local configuration parameters, implement custom ad loading logic
- (void)registerClickableViews:(NSArray<UIView *> *)clickableViews withContainer:(UIView *)container registerArgument:(ATNativeRegisterArgument *)registerArgument clickableViews: Array of clickable views
container: Container view
registerArgument: Registration parameters
Implement native ad click event registration and rendering logic
- (void)setNativeADConfiguration:(ATNativeAdRenderConfig *)configuration configuration: Native ad rendering configuration Set native ad rendering configuration parameters

3. Callback Method Description

Native ad adapters support the following callback methods, which inherit from the ATBaseTrackProtocol and ATNativeTrackProtocol protocols:

3.1 Basic Ad Event Callbacks

Method Description
- (void)atOnAdMetaLoadFinish:(NSDictionary *)adExtra Callback to developer when ad data loading is complete
- (void)atOnAdLoadFailed:(NSError *)error adExtra:(NSDictionary *)adExtra Callback to developer when ad loading fails
- (void)atOnAdShow:(NSDictionary *)adExtra Callback to developer when ad is successfully shown
- (void)atOnAdShowFailed:(NSError *)error extra:(NSDictionary *)extraDic Callback to developer when ad show fails
- (void)atOnAdClick:(NSDictionary *)adExtra Callback to developer when ad is clicked by user
- (void)atOnAdWillClosed:(NSDictionary *)extra Callback to developer when ad is about to close
- (void)atOnAdClosed:(NSDictionary *)extra Callback to developer when ad is closed
- (void)atOnAdDetailWillShow:(NSDictionary *)extra Callback to developer when ad detail page is about to show
- (void)atOnAdDetailClosed:(NSDictionary *)extra Callback to developer when ad detail page is closed
- (void)atOnAdDeeplinkOrJumpResult:(BOOL)success Callback to developer with ad deeplink jump result
- (void)atOnAdVideoStart:(NSDictionary *)extra Callback to developer when ad video starts playing
- (void)atOnAdVideoEnd:(NSDictionary *)extra Callback to developer when ad video ends playing
- (void)atOnAdDidFailToPlayVideo:(NSError *)error extra:(NSDictionary *)extraDic Callback to developer when ad video fails to play
- (void)atOnAdDidRevenue:(NSDictionary *)extraDic Ad revenue callback to developer

3.2 Native Ad Specific Event Callbacks

Method Description
- (void)atOnNativeAdLoadedArray:(NSArray <ATCustomNetworkNativeAd >)nativeObjectArray adExtra:(NSDictionary *)adExtra Callback to developer when native ad loads successfully
- (void)atOnNativeAdDidEnterFullScreenVideoInAdViewWithAdExtra:(NSDictionary *)adExtra Callback to developer when native ad enters full-screen video mode
- (void)atOnNativeAdDidExitFullScreenVideoInAdViewWithAdExtra:(NSDictionary *)adExtra Callback to developer when native ad exits full-screen video mode

4. Implementation Steps

4.1 Implement DemoCustomNativeObject.h

  1. Import relevant header files
  2. Inherit from ATCustomNetworkNativeAd base class
  3. Add third-party SDK native ad related properties

Example:

objc Copy
#import <AnyThinkSDK/AnyThinkSDK.h>
#import <Foundation/Foundation.h>
#import "DemoCustomAdapterCommonHeader.h"

@interface DemoCustomNativeObject : ATCustomNetworkNativeAd

@property (nonatomic, strong) YourNativeFeedAdModel *feedAdModel;

@property (nonatomic, strong) id<YourFeedAdMeta> feedAdMetaad;

@end

4.2 Implement DemoCustomNativeObject.m

  1. Implement the ad registration container method and handle both self-rendering and template rendering modes. If your custom ad platform only has one rendering mode, handle the branch logic according to your actual situation.
objc Copy
- (void)registerClickableViews:(NSArray<UIView *> *)clickableViews withContainer:(UIView *)container registerArgument:(ATNativeRegisterArgument *)registerArgument {
     
    if (self.nativeAdRenderType == ATNativeAdRenderExpress) {
        // Handle parameters needed for third-party SDK template ads here, assign to third-party ad object
 
        return;
    }
    // Handle parameters needed for third-party SDK self-rendering ads here, usually register events
   
}
  1. Implement configuration setting method:
objc Copy
- (void)setNativeADConfiguration:(ATNativeAdRenderConfig *)configuration {
    // configuration object is passed from external, extract properties and set to third-party SDK
    self.configuration = configuration;
    [self getYourFeedVideoView].presentVc = configuration.rootViewController;
}
  1. Implement resource cleanup method:
objc Copy
- (void)dealloc {
    [[self getYourFeedVideoView] unregisterDataObject];
    [self.feedAdMetaad unAttachAd];
}

4.3 Implement DemoCustomNativeDelegate.h

  1. Import header file #import <AnyThinkSDK.h>
  2. Add property: @property (nonatomic,strong) ATNativeAdStatusBridge *adStatusBridge;
  3. Add property: @property (nonatomic, strong) ATAdMediationArgument *adMediationArgument;
  4. Conform to your third-party ad SDK native ad callback protocol

Example:

objc Copy
#import <Foundation/Foundation.h>
#import "DemoCustomAdapterCommonHeader.h"

@interface DemoCustomNativeDelegate : NSObject<YourNativeFeedAdDelegate,YourFeedVideoDelegate>

@property (nonatomic,strong) ATNativeAdStatusBridge *adStatusBridge;

@property (nonatomic, strong) ATAdMediationArgument *adMediationArgument;

@end

4.4 Implement DemoCustomNativeDelegate.m

  1. Implement your third-party SDK protocol methods, such as ad load success, ad click, ad close, etc.
  2. In the third-party SDK's ad load success event, assemble the third-party ad SDK's native ad object into the DemoCustomNativeObject object required by our aggregation SDK, and call to notify us of successful ad loading, for example:
objc Copy
/**
 *  Third-party new native ad load success callback, returns array of ad materials
 */
- (void)yourNativeFeedAdLoaded:(YourNativeFeedAd *)nativeFeedAd feedAds:(NSArray <YourNativeFeedAdModel *> *)feedAds { // This is third-party SDK protocol method, called when ad loads successfully
    self.nativeFeedAd = nativeFeedAd;
    [self nativeRenderingFeedAds:feedAds];
}

- (void)nativeRenderingFeedAds:(NSArray <YourNativeFeedAdModel *> *)feedAds {
    
    YourNativeFeedAdModel *feedAdModel = feedAds.firstObject;
    // Determine if it's self-rendering ad or template ad, handle different logic accordingly
    if (feedAdModel.isNativeExpress) {
        [self _expressRenderingFeedAds:feedAds];
    }else{
        [self _selfRenderingFeedAds:feedAds];
    }
}
  1. In the third-party SDK's ad load failure event, call to notify us of ad load failure, for example:
objc Copy
/**
 *  New native ad load failure callback
 */
- (void)yourNativeFeedAdError:(YourNativeFeedAd *)nativeFeedAd withError:(NSError *)error { // This is third-party SDK protocol method, called when ad load fails
    // Notify us of load failure
    [self.adStatusBridge atOnAdLoadFailed:error adExtra:nil];
}
  1. Implement self-rendering ad handling method:
objc Copy
- (void)_selfRenderingFeedAds:(NSArray <YourNativeFeedAdModel *> *)feedAds {
    
    NSMutableArray *offerArray = [NSMutableArray array];
    
    // If client-side bidding needs to be implemented, also need to get third-party ad price
    NSDictionary *infoDic = [DemoCustomBaseAdapter getC2SInfo:[feedAds.firstObject ecpm]];
    
    [feedAds enumerateObjectsUsingBlock:^(YourNativeFeedAdModel * _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) {
                
        id<YourFeedAdMeta> ad = obj.adMaterialMeta;
        // Create native ad object required by our SDK based on third-party content
        DemoCustomNativeObject *nativeObject = [[DemoCustomNativeObject alloc] init];
        nativeObject.feedAdMetaad = ad;
        nativeObject.nativeAdRenderType = ATNativeAdRenderSelfRender;
        nativeObject.title = ad.metaContent;
        nativeObject.mainText = ad.metaContent;
        nativeObject.ctaText = ad.metaActionTitle;
        nativeObject.rating = @([ad.metaAppScore doubleValue]);
        nativeObject.appPrice = ad.metaAppPrice;
        nativeObject.videoDuration = ad.metaVideoDuration;
        
        CGSize imageSize = ad.metaMainImageSize;
        nativeObject.mainImageWidth = imageSize.width;
        nativeObject.mainImageHeight = imageSize.height;

        nativeObject.iconUrl = ad.metaIcon;
        nativeObject.imageUrl = ad.metaImageUrls.firstObject;
        nativeObject.imageList = ad.metaImageUrls;
        // Video ad related handling, if third-party has video ads
        if (ad.metaCreativeType == YourCreativeTypeVideo) {
            
            nativeObject.isVideoContents = YES;
            
            YourFeedVideoConfig *config = [YourFeedVideoConfig new];
            config.isMute = [self.adMediationArgument.serverContentDic[@"video_muted"] intValue] == 0 ? NO : YES;;
            config.isAutoPlay = NO;
            
            YourFeedVideoView *feedVideoView = [[YourFeedVideoView alloc] init];
            feedVideoView.videoConfig = config;
            // Important: Set delegate
            feedVideoView.delegate = self;
            // Important: Assign media view
            nativeObject.mediaView = feedVideoView;
        }
 
        [offerArray addObject:nativeObject];
    }];
    // Pass assembled object back to our SDK
    [self.adStatusBridge atOnNativeAdLoadedArray:offerArray adExtra:infoDic];
}
  1. Implement template rendering ad handling method:
objc Copy
- (void)_expressRenderingFeedAds:(NSArray <YourNativeFeedAdModel *> *)feedAds {
    
    NSMutableArray *offerArray = [NSMutableArray array];
    // If client-side bidding needs to be implemented, also need to get third-party ad price
    NSDictionary *infoDic = [DemoCustomBaseAdapter getC2SInfo:[feedAds.firstObject ecpm]];
    
    [feedAds enumerateObjectsUsingBlock:^(YourNativeFeedAdModel * _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) {
        
        UIView *nativeAdView = obj.feedView;
        // Create native ad object required by our SDK based on third-party content
        DemoCustomNativeObject *nativeObject = [[DemoCustomNativeObject alloc] init];
        nativeObject.feedAdModel = obj;
        nativeObject.templateView = nativeAdView;
        nativeObject.nativeAdRenderType = ATNativeAdRenderExpress;
        nativeObject.nativeExpressAdViewWidth = nativeAdView.frame.size.width;
        nativeObject.nativeExpressAdViewHeight = nativeAdView.frame.size.height;
        nativeObject.isVideoContents = obj.isVideo;
        
        [offerArray addObject:nativeObject];
    }];
    // Pass assembled object back to our SDK
    [self.adStatusBridge atOnNativeAdLoadedArray:offerArray adExtra:infoDic];
}
  1. Refer to our SDK's ATNativeTrackProtocol and ATBaseTrackProtocol protocols, implement other ad events and notify us, for example:
objc Copy
/**
 *  Ad clicked
 */
- (void)yourNativeFeedAdClick:(YourNativeFeedAdModel *)feedAd {
    [self.adStatusBridge atOnAdClick:nil];
}

/**
 * Note⚠️: This callback is triggered when the ad material is ⚠️[template ad]⚠️
 *  Ad closed
 *  Detail: Callback after ad click close
 */
- (void)yourNativeFeedAdClosed:(YourNativeFeedAdModel *)feedAd {
    [self.adStatusBridge atOnAdClosed:nil];
}

/**
 * Note⚠️: This callback is triggered when the ad material is ⚠️self-rendering ad⚠️
 * Callback when built-in AppStore or built-in browser is closed after native ad click
 */
- (void)yourNativeFeedAdDetailClosed {
    [self.adStatusBridge atOnAdDetailClosed:nil];
}

4.5 Implement DemoCustomNativeAdapter.h

  1. Inherit from base Adapter, in this example: DemoCustomBaseAdapter
  2. Import header file #import <AnyThinkSDK.h>
  3. Conform to ATBaseNativeAdapterProtocol protocol

4.6 Implement DemoCustomNativeAdapter.m

  1. Add the following properties:
objc Copy
@interface DemoCustomNativeAdapter()

// Implemented in section 4.3 of this document
@property (nonatomic, strong) DemoCustomNativeDelegate * nativeDelegate;

// Third-party SDK native ad object
@property (nonatomic, strong) YourNativeFeedAd           * nativeExpressAd;

@end
  1. Initialize nativeDelegate property
objc Copy
#pragma mark - lazy
- (DemoCustomNativeDelegate *)nativeDelegate{
    if (_nativeDelegate == nil) {
        _nativeDelegate = [[DemoCustomNativeDelegate alloc] init];
        _nativeDelegate.adStatusBridge = self.adStatusBridge;
    }
    return _nativeDelegate;
}
  1. Implement ad loading method:
objc Copy
#pragma mark - init
- (void)loadADWithArgument:(ATAdMediationArgument *)argument {
   
    dispatch_async(dispatch_get_main_queue(), ^{
        // Get necessary loading information through argument object, such as size, create necessary parameters, prepare to pass to third-party native loading method, start loading ads
        self.nativeExpressAd = [[YourNativeFeedAd alloc]init];
        // Note: Set delegate to DemoCustomNativeDelegate
        self.nativeExpressAd.delegate = self.nativeDelegate;
        
        self.nativeDelegate.adMediationArgument = argument;
        
        YourNativeFeedAdConfigParams *adParam = [[YourNativeFeedAdConfigParams alloc]init];
        adParam.adCount = [argument.at_serverDic[@"request_num"] intValue] ? [argument.at_serverDic[@"request_num"] intValue] : 1;
        adParam.videoMuted = [argument.at_serverDic[@"video_muted"] intValue] == 0 ? NO : YES;;
        adParam.isAutoPlay = NO;
        
        if ([argument.localInfoDic[kATExtraInfoNativeAdSizeKey] respondsToSelector:@selector(CGSizeValue)]) {
            CGSize size = [argument.localInfoDic[kATExtraInfoNativeAdSizeKey] CGSizeValue];
            adParam.prerenderAdSize = size;
        }
        [self.nativeExpressAd loadAdWithPid:argument.serverContentDic[@"slot_id"]  adParam:adParam];
    });
}

5. Advanced Settings

The implementation method is to implement the protocol methods in ATAdLoadedNativeDataSource in DemoCustomNativeObject.m. The video control content is as follows:

objc Copy
@protocol ATAdLoadedNativeDataSource

#pragma mark - Video
/**
 * The duration of the video ad playing, unit ms
 */
- (CGFloat)videoPlayTime;
/**
 * Video ad duration, unit ms
 */
- (CGFloat)videoDuration;
/**
 Play mute switch
 @param flag whether to mute
 */
- (void)muteEnable:(BOOL)flag;
/**
 * The video ad play
 */
- (void)videoPlay;
/**
 * set voice button hidden, only suport TopOn Adx ad
 */
- (void)updateVoiceBtnHidden:(BOOL)hidden;
/**
 * The video ad pause
 */
- (void)videoPause;

- (void)setVideoAutoPlay:(NSInteger)autoPlayType;

/// The destroy  network native ad
- (void)destroyNative;
  
@end

For example, if I need external code to control whether the video is muted, I need to implement in DemoCustomNativeObject.m:

objc Copy
@implementation DemoCustomNativeObject

- (void)muteEnable:(BOOL)flag {
    
    // Get the mute flag passed from external, pass to third-party SDK
    
}

...... other integration code
@end

Last modified: 2025-10-10Powered by