💡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.
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
You need to inherit from DemoCustomBaseAdapter and override the relevant methods:
loadADWithArgument: method will be calledregisterClickableViews:withContainer:registerArgument: method will be calledsetNativeADConfiguration: 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 |
Native ad adapters support the following callback methods, which inherit from the ATBaseTrackProtocol and ATNativeTrackProtocol protocols:
| 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 |
| 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 |
- Import relevant header files
- Inherit from
ATCustomNetworkNativeAdbase class- 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
- 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 }
- 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; }
- Implement resource cleanup method:
objc Copy- (void)dealloc { [[self getYourFeedVideoView] unregisterDataObject]; [self.feedAdMetaad unAttachAd]; }
- Import header file
#import <AnyThinkSDK.h>- Add property:
@property (nonatomic,strong) ATNativeAdStatusBridge *adStatusBridge;- Add property:
@property (nonatomic, strong) ATAdMediationArgument *adMediationArgument;- 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
- Implement your third-party SDK protocol methods, such as ad load success, ad click, ad close, etc.
- In the third-party SDK's ad load success event, assemble the third-party ad SDK's native ad object into the
DemoCustomNativeObjectobject 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]; } }
- 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]; }
- 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]; }
- 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]; }
- Refer to our SDK's
ATNativeTrackProtocolandATBaseTrackProtocolprotocols, 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]; }
- Inherit from base Adapter, in this example:
DemoCustomBaseAdapter- Import header file
#import <AnyThinkSDK.h>- Conform to
ATBaseNativeAdapterProtocolprotocol
- 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
- Initialize
nativeDelegatepropertyobjc Copy#pragma mark - lazy - (DemoCustomNativeDelegate *)nativeDelegate{ if (_nativeDelegate == nil) { _nativeDelegate = [[DemoCustomNativeDelegate alloc] init]; _nativeDelegate.adStatusBridge = self.adStatusBridge; } return _nativeDelegate; }
- 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]; }); }
The implementation method is to implement the protocol methods in
ATAdLoadedNativeDataSourceinDemoCustomNativeObject.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; @endFor 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