Menu

Self-rendering ads

1. Introduction

Self-rendering ads are a relatively advanced use in native advertising. Developers can obtain all the creative content of the ads to render ads with customized layouts. Generally, developers will implement it nested in the layout of the product itself. As shown in the screenshot below

Fixed position DisplayInformation flow list display
native_one_demo_pic_thumbnative_list_demo_pic_thumb

1.1 Integration suggestions

1. Load ads

    • To load ads through loadADWithPlacementID , please call the loading method in advance to request the ads. For example, you can preload the ads after opening the screen so that they can be displayed quickly when the ads need to be triggered.
    • When loading, pass in the size you expect and let the advertising platform adapt. If the height is not limited to 0, the platform will adjust it according to the width or its own rules. Returns the dimensions of the material.

2. Display ads

    • You can use the getCurrentNativeAdRenderType method in the ATNativeADView class to determine whether the advertisement is a self-rendering type of advertisement.
    • ATNativeAdRenderSelfRender Ads are provided to developers in the form of source materials for rendering, except for some advertising platforms that directly provide large images and the mediaview of the video.
    • Native ads can only be displayed in the same place at the same time. Otherwise, the Native ad displayed initially will not be displayed or clicked normally.
    • In the process of integrating Native advertising, the developer selects the material elements that need to be displayed. After display, the didShowNativeAdInAdView callback is triggered to indicate effective display.
    • Involves the refresh function and corresponding attention points, but it is not limited to these points. Developers can add logic by themselves:
      • To refresh new ads, you need to remove the old ATNativeADView ads and then add new ads
      • There are no new ads. Then you only need to display the previously saved ATNativeADView ad view, and there is no need to go through another round of rendering process.
    • According to the instructions for displaying ads below, complete the display logic of the ads. The main operations include:
      1. Get the ATNativeAdOffer material object;
      2. Generate the ATNativeADView container object;
      3. If there are templates, large pictures, videos and other materials, mediaview is required and added to the container view;
      4. Register click events of related controls;
      5. Render the native ad layout;
      6. Display the ATNativeADView container object.

3. Close ads

    • Remove the closed ATNativeADView view in the didTapCloseButtonInAdView callback

1.2 Notes

    • To ensure that you can get ads faster and at a higher price, it is recommended to get one AD at a time and perform the next AD load after getting it. Please do not perform in didFailToLoadADWithPlacementID callback AD loading method, otherwise it will cause a lot of useless requests and caton may result in application.
    • You are advised to configure a preset policy to improve the advertising loading effect for the first cold start. For details and access tutorials, see the instructions for using SDK Preset policies.
    • For the convenience of using a funnel statement analysis advertising scenario, it is suggested that the need to show the timing of the native advertising calls entryNativeScenarioWithPlacementID, to record the scene statistics.

2.API Description

2.1 Load ads

ATAdManager : Native ads management class

MethodDescription
sharedManagerGet ATAdManager singleton object
loadADWithPlacementID: extra: delegate:Native ads loading method
placementId: TopOn's advertising slot id
extra: local configuration parameters
delegate: proxy object

Sample code:

#import <AnyThinkNative/AnyThinkNative.h>

- (void)loadAd {
    CGSize size = CGSizeMake(UIScreen.mainScreen.bounds.size.width, 350.0f);
    NSDictionary *extra = @{
        /*
            Template AD size, through the advertising platform, the advertising platform will return a similar size of the optimal template AD, 
            if there is no specific size requirements, you can pass the height 0, by the platform adaptation width to return the appropriate height.
        */
        kATExtraInfoNativeAdSizeKey:[NSValue valueWithCGSize:size]
    };
    [[ATAdManager sharedManager] loadADWithPlacementID:@"your Native placement id" extra:extra delegate:self];
}

2.2 Display ads

MethodDescription
getNativeAdOfferWithPlacementID:Get the native ads offer
placementId: TopOn's advertising slot id
getNativeAdOfferWithPlacementID: scene:Get the native ads offer by passing in the scene id
placementId: TopOn's advertising slot id
scene: scene id , there is no space to pass @"", please see to scene statistics.
nativeAdReadyForPlacementID:Determine whether there is currently an ad that can be displayed
placementId: TopOn's advertising slot id

ATNativeADView The object of the native advertising view, the attribute description is as follows:

Methods Description
initWithConfiguration: currentOffer: placementIDInitialize NativeADView object
configuration: NativeADView configured object
currentOffer: obtained ATNativeAdOffer object
placementID: advertising slot id
getNetworkShakeViewWithFrame:Gets the Shake component and returns null if the AD does not support the Shake feature.
(v6. 1.40 and above are supported, currently only supported by Baidu)
frame: the width of the component, not less than 80dp, the height of the component, not less than 80dp
getNetworkSlideViewWithFrame:repeat: animationWidth: animationHeightGet the slide-and-slide component. The sliding area is controlled by the container size , if the advertisement does not support sliding, return null
(supported by v6.2.60 and above, currently only supported by Baidu)
animationWidth: the width of the sliding guide area
animationHeight: the height of the sliding guide area
repeat: The number of repetitions of the animation, the component will be automatically hidden after it ends.
networkFirmIDThe ID corresponding to the current advertising platform, used to distinguish advertising platforms, refer to Network Firm Id Table.
getNativeAdTypeGet ad type
ATNativeAdTypeFeed: Information flow advertising (native advertising)
ATNativeAdTypePaster: Pre-roll advertising
getCurrentNativeAdRenderTypeGet ad rendering type
ATNativeAdRenderSelfRender: Self-rendering
ATNativeAdRenderExpress: template rendering
getMediaViewGet the MediaView of the third-party platform to display videos.
initWithConfigurationInitialize the configuration object of NativeADView
registerClickableViewArrayRegister click event
prepareWithNativePrepareInfoBind the self-rendering view to the ATNativeADView view control
videoPlayTimeGet video playback progress (CGFloat type, unit: seconds), supported platforms are as follows:
GDT: self-rendering
videoDurationGet the total duration of the video ( CGFloat type, unit: seconds), supported platforms are as follows:
Pangolin: template rendering
GDT: self-rendering, template rendering, template rendering 2.0
muteEnableSet whether to mute the video during playback. The supported platforms are as follows:
GDT: Self-rendering
videoPlayResume playing the paused video. The supported platforms are as follows:
GDT: Self-rendering
videoPausePause the playback of video ads. The supported platforms are as follows:
GDT: Self-rendering

ATNativeAdOffer The object of native advertising management material. The attribute description is as follows:

MethodsDescription
nativeAdnative Ad Material
networkFirmIDThe ID corresponding to the current advertising platform, used to distinguish the advertising platform, refer to Network Firm Id Table
adOfferInfoGet the ad cache information with the highest priority in the current ad slot, mainly including third parties Aggregation platform id information Callback information description
rendererWithConfiguration: selfRenderView: nativeADView:Call this method before displaying the ad to render the native ad container view
configuration: configuration object of ATNativeADView
selfRenderView: self-rendered view
nativeADView: ad view

2.2.1 Implement Custom Native Ad View

To display a Native self-rendering ad, you need to define a custom view, which is responsible for displaying native self-rendering ads and needs to initialize the display of controls.

As shown below:

@interface ATNativeSelfRenderView : UIView

@property(nonatomic, strong) UILabel *advertiserLabel;
@property(nonatomic, strong) UILabel *textLabel;
@property(nonatomic, strong) UILabel *titleLabel;
@property(nonatomic, strong) UILabel *ctaLabel;
@property(nonatomic, strong) UILabel *ratingLabel;
@property(nonatomic, strong) UIImageView *iconImageView;
@property(nonatomic, strong) UIImageView *mainImageView;
@property(nonatomic, strong) UIImageView *logoImageView;
@property(nonatomic, strong) UIButton *dislikeButton;

@property(nonatomic, strong) UIView *mediaView;

- (instancetype) initWithOffer:(ATNativeAdOffer *)offer;

@end

Here, your ad view needs to do two things:

1) Create the UI elements that the ad view needs to display, assign the obtained material to the UI element:

- (void)addView{    
    self.titleLabel = [[UILabel alloc]init];
    self.titleLabel.font = [UIFont boldSystemFontOfSize:18.0f];
    self.titleLabel.textColor = [UIColor blackColor];
    self.titleLabel.textAlignment = NSTextAlignmentLeft;
    self.titleLabel.userInteractionEnabled = YES;
    [self addSubview:self.titleLabel];
    ......
}

- (void)setupUI{
 
    if (self.nativeAdOffer.nativeAd.icon) {
            self.iconImageView.image = self.nativeAdOffer.nativeAd.icon;
    } else {
            [self.iconImageView sd_setImageWithURL:[NSURL URLWithString:self.nativeAdOffer.nativeAd.iconUrl]];
    }
 
    self.advertiserLabel.text = self.nativeAdOffer.nativeAd.advertiser;
    ......
}

2 ) Layout of UI elements

In our sample code, we use Masonry layout of UI elements

-(void) makeConstraintsForSubviews {
    [self.titleLabel mas_makeConstraints:^(MASConstraintMaker *make) {
        make.left.equalTo(self).offset(100);
        make.right.equalTo(self).offset(-40);
        make.height.equalTo(@20);
        make.top.equalTo(self).offset(20);
    }];
    ......
}

You can also use struts&springs layout technology. When using this method, it is recommended You override the layoutSubviews method and set a frame for your subviews. It's entirely up to you which layout technique you use, and you can choose whatever suits you.

Note: Since Admob's Native needs to be rendered using GADNativeAdView, xib and Storyboard layouts are currently not supported.

2.2.2 Custom View displays Native

Native advertising integration process:

1. Get the native advertising ATNativeAdOffer object

ATNativeAdOffer *offer = [[ATAdManager sharedManager] getNativeAdOfferWithPlacementID:@"your Native placement id"];

2. Generate a container for native display

ATNativeADConfiguration *config = [[ATNativeADConfiguration alloc] init];
config.ADFrame = CGRectMake(.0f, 64.0f, CGRectGetWidth(self.view.bounds), 350.0f);
// Here, as the default value, you can use [nativeADView getMediaView] in ATNativeADView to get mediaView for dynamic setting constraints.
config.mediaViewFrame = CGRectMake(0, 150.0f, CGRectGetWidth(self.view.bounds), 350.0f - 150.0f);
config.delegate = self;
config.rootViewController = self;

ATNativeADView *nativeADView = [[ATNativeADView alloc] initWithConfiguration:config currentOffer:offer placementID:@"your Native placement id"];

3. Get mediaview, which is used to display videos, pictures, etc. from third-party advertising platforms. If not provided, nil is returned.

// Note: On the GDT advertising platform, both video ads and image ads will return this value.
UIView *mediaView = [nativeADView getMediaView];

4. Register click event

[nativeADView registerClickableViewArray:array];

5 Render ads

[offer rendererWithConfiguration:config selfRenderView:selfRenderView nativeADView:nativeADView];

Complete display code

-(void) showAD {

    ATNativeADConfiguration *config = [[ATNativeADConfiguration alloc] init];
    config.ADFrame = CGRectMake(.0f, 64.0f, CGRectGetWidth(self.view.bounds), 350.0f);
    config.mediaViewFrame = CGRectMake(0, 150.0f, CGRectGetWidth(self.view.bounds), 350.0f - 150.0f);
    config.delegate = self;
    config.rootViewController = self;

    // Get advertising material
    ATNativeAdOffer *offer = [[ATAdManager sharedManager]
                getNativeAdOfferWithPlacementID:@"your Native placement id"];

     // Create a self-rendering view and use the offer material to assign values
    ATNativeSelfRenderView *selfRenderView = [[ATNativeSelfRenderView alloc] initWithOffer:offer];

    // Create a native AD display container view.
    ATNativeADView *nativeADView = [[ATNativeADView alloc] initWithConfiguration:config currentOffer:offer placementID:@"your Native placement id"];

    UIView *mediaView = [nativeADView getMediaView];

    // Register the click event, it is best not to add the superview of the information flow as a whole to the click event, 
    // otherwise there may be a click close button, but also trigger the click information flow event.
    NSMutableArray *array = [@[selfRenderView.iconImageView] mutableCopy];
    if (mediaView) {
        [array addObject:mediaView];
        [selfRenderView addSubview:mediaView];
            
        [mediaView mas_updateConstraints:^(MASConstraintMaker *make) {
            make.left.right.bottom.equalTo(selfRenderView);
            make.top.equalTo(selfRenderView.mainImageView.mas_top);
        }];
    }
    [nativeADView registerClickableViewArray:array];

    // Bind a self-rendering view
    // Assuming that a large image or video stream is not required, loadPrepareInfo does not need to assign values to mediaView and mainImageView.
    ATNativePrepareInfo *info = [ATNativePrepareInfo loadPrepareInfo:^(ATNativePrepareInfo * _Nonnull prepareInfo) {
        prepareInfo.textLabel = selfRenderView.textLabel;
        ......
    }];
    [nativeADView prepareWithNativePrepareInfo:info];

     // render Ad.
     [offer rendererWithConfiguration:config selfRenderView:selfRenderView nativeADView:nativeADView];
      // show Ad.
      [self.view addSubview:nativeADView];
}

2.2.3 Self-rendering description(Note)

ATNativeAdOffer.nativeAd: Creative object , the following materials may appear to be null, because some advertising platforms may not necessarily have all the material information. Another point to note is to pay attention to the agent callback of the display. If the callback of the display is not triggered, it may be on the third-party platform. Represents as an invalid display and needs to be restyled.

There is a case where mediaView is not added to the view.

//  get mediaView
UIView *mediaView = [nativeADView getMediaView];

The SDK will report a warning:

Message: The current integration is wrong, Please follow the document to integrate.

Then at this time, we should pay attention to whether there is a successful callback after the display, and a callback is an effective display.

/// Native ads displayed successfully
- (void)didShowNativeAdInAdView:(ATNativeADView *)adView
                    placementID:(NSString *)placementID
                          extra:(NSDictionary *)extra;

In addition, after version 6.2.95, logo view will be added inside the self-rendered native AD view, which can be adjusted through the API:

ATNativeADConfiguration *config = [[ATNativeADConfiguration alloc] init];
config.logoViewFrame = CGRectMake(<#CGFloat x#>, <#CGFloat y#>, <#CGFloat width#>, <#CGFloat height#>);

If you want to dynamically constrain the logo view, you can refer to the code:

    // Get a native AD display container view
    ATNativeADView *nativeADView = [[ATNativeADView alloc] initWithConfiguration:config currentOffer:offer placementID:self.placementID];
    
    // The nativeADView logoImageView for layout, Masonry, for example
    [nativeADView.logoImageView mas_makeConstraints:^(MASConstraintMaker *make) {
       
    }];
    
    [nativeADView setNeedsLayout];
    [nativeADView layoutIfNeeded];
    
    // Call the above logic before render
    // - (void) rendererWithConfiguration:(ATNativeADConfiguration*)configuration selfRenderView:(UIView *_Nullable)selfRenderView nativeADView:(ATNativeADView *)nativeADView;

If you do not need this logo view, you can hide the logo view, please refer to the following code:

    // Get a native AD display container view
    ATNativeADView *nativeADView = [[ATNativeADView alloc] initWithConfiguration:config currentOffer:offer placementID:self.placementID];
    
    // Rendering advertising
    [offer rendererWithConfiguration:config selfRenderView:selfRenderView nativeADView:nativeADView];
    // Needs to be called after render
    nativeADView.logoImageView.hidden = YES;

UI elements include:

Reminder again: Integrated native self-rendering due to different style requirements, we should focus on whether there is a proxy callback for display after advertising display to ensure the effectiveness of advertising display.

Meta(Facebook):If getMediaView in the ATNativeADView class returns mediaView, it must be added to the self-rendered view, otherwise use Meta's native banner style.

InMobi:The getMediaView in the ATNativeADView class returns mediaView, which needs to be added to the self-rendered view or it might be inefficiently displayed.

UIReturn typeDescription
titleNSStringAd title
mainTextNSStringAd description
ctaTextNSStringAd CTA button text
advertiserNSStringAdvertiser name
iconUrlNSStringAd icon url
logoUrlNSStringAdvertising platform logo url
imageUrlNSStringLarge image url
imageListNSArrayPicture array
mainImageWidthCGFloatLarge image width
mainImageHeightCGFloatLarge picture height
iconUIImageAdvertising icon image
logoUIImageAdvertising platform logo image
mainImageUIImageLarge image
isVideoContentsBOOLWhether it is a video ad
videoUrlNSStringVideo url
videoDurationNSIntegerVideo duration
videoAspectRatioCGFloatVideo size Scale
interactionTypeNSIntegerAdvertising Supported jump types
mediaExtNSDictionaryMedia extension data
sourceNSStringApplication source, market
ratingNSNumberAd's rating
commentNumNSIntegerNumber of comments
appSizeNSIntegerAd installation package size
appPriceNSStringapp purchase price
domainNSStringDomain name (only supported by the Yandex platform)
warningNSStringWarning (only supported by Yandex platform)

For video ads, there is a media view playing the video, which is obtained through the following API. Some third parties display their cover image in the media view, and some display both media view and image view. .

UIView *mediaView = [nativeADView getMediaView];

Note: The advertising specifications for TT(CSJ) information flow advertising are as follows:

    • TT(CSJ) requires rendering titleLabel or textLabel
    • TT(CSJ) at least one image needs to be rendered, that is, it needs to rendericonImageView or mainImageView or media view
    • TT(CSJ) AdLogo must be displayed

ATImageLoader: provided by SDK, used for Display network images(optional)

MethodParameterDescription
loadImageWithURL(NSURL URL)Display network pictures
URL: network picture url

2.3 Scene Statistics

MethodDescription
entryNativeScenarioWithPlacementID:scene:Enter the corresponding advertising space Business scene cache status statistics placementId: Advertising slot Id scene: Ad display scene, scene parameters can be created from the background, if there is no empty space, please refer to Business Scene cache status statistics
/* To collect scene arrival rate statistics, you can view related information https://docs.toponad.com/#/zh-cn/ios/NetworkAccess/scenario/scenario 
Call the "Enter AD scene" method when an AD trigger condition is met, such as: 
** The scenario is a pop-up AD after the cleanup, which is called at the end of the cleanup. 
* 1、Call entryXXX to report the arrival of the scene. 
* 2、Call xxRewardedVideoReadyForPlacementID. 
* 3、Call showXX to show AD view. 
* (Note the difference between auto and manual) */
[[ATAdManager sharedInstance] entryNativeScenarioWithPlacementID:@"your Native placement id"" scene:@"your scenarioID"];
// Check to see if the AD is ready before showing
if ([[ATAdManager sharedManager] nativeAdReadyForPlacementID:@"your Native placementID"]) {
    ATNativeAdOffer *offer = [[ATAdManager sharedManager] getNativeAdOfferWithPlacementID:@"your Native placementID" scene:@"your scenarioID"];
}  

2.4 Delegate callback

ATAdLoadingDelegate delegate method

MethodsDescription
didFinishLoadingADWithPlacementID:corresponds to advertising slot id Loading success callback
placementId: Advertisement slot Id
didFailToLoadADWithPlacementID: error:Corresponding to advertising slot id loading failure callback
placementId: advertising slot Id
error: advertising loading failure information

ATNativeADDelegate delegate method

MethodsDescription
didShowNativeAdInAdView: placementID: extra:Native did show
didClickNativeAdInAdView: placementID: extra:Native did click
didStartPlayingVideoInAdView: placementID: extra:Native video AD begins
didEndPlayingVideoInAdView: placementID: extra:Native video AD ends
didEnterFullScreenVideoInAdView: placementID: extra:Native enters a full-screen video AD
didExitFullScreenVideoInAdView: placementID: extra:Native exits full-screen video ads
didTapCloseButtonInAdView: placementID: extra:Click the close button in the Native AD
didLoadSuccessDrawWith: placementID: extra:The Native draw advertisement was successfully loaded
didDeepLinkOrJumpInAdView: placementID: extra: result:Native AD click skip is Deeplink form, currently only for TopOn Adx AD return
didCloseDetailInAdView: placementID: extra:Native AD Click to close the details page
extra: Extended parameter reference Documentation
#pragma mark - delegate with loading
-(void) didFinishLoadingADWithPlacementID:(NSString *)placementID {
    NSLog(@"ATNativeViewController:: didFinishLoadingADWithPlacementID:%@", placementID);
}

-(void) didFailToLoadADWithPlacementID:(NSString *)placementID error:(NSError *)error {
    NSLog(@"ATNativeViewController:: didFailToLoadADWithPlacementID:%@ error:%@", placementID, error);
}

#pragma mark - delegate with native ad
-(void) didStartPlayingVideoInAdView:(ATNativeADView*)adView placementID:(NSString*)placementID extra:(NSDictionary *)extra{
    NSLog(@"ATNativeViewController:: didStartPlayingVideoInAdView:placementID:%@with extra: %@", placementID,extra);
}

-(void) didEndPlayingVideoInAdView:(ATNativeADView*)adView placementID:(NSString*)placementID extra:(NSDictionary *)extra{
    NSLog(@"ATNativeViewController:: didEndPlayingVideoInAdView:placementID:%@ extra: %@", placementID,extra);
}

-(void) didClickNativeAdInAdView:(ATNativeADView*)adView placementID:(NSString*)placementID extra:(NSDictionary *)extra{
    NSLog(@"ATNativeViewController:: didClickNativeAdInAdView:placementID:%@ with extra: %@", placementID,extra);
}

- (void) didDeepLinkOrJumpInAdView:(ATNativeADView *)adView placementID:(NSString *)placementID extra:(NSDictionary *)extra result:(BOOL)success {
    NSLog(@"ATNativeViewController:: didDeepLinkOrJumpInAdView:placementID:%@ with extra: %@, success:%@", placementID,extra, success ? @"YES" : @"NO");
}

-(void) didShowNativeAdInAdView:(ATNativeADView*)adView placementID:(NSString*)placementID extra:(NSDictionary *)extra{
    NSLog(@"ATNativeViewController:: didShowNativeAdInAdView:placementID:%@ with extra: %@", placementID,extra);
}

-(void) didEnterFullScreenVideoInAdView:(ATNativeADView*)adView placementID:(NSString*)placementID extra:(NSDictionary *)extra{
    NSLog(@"ATNativeViewController:: didEnterFullScreenVideoInAdView:placementID:%@", placementID);
}

-(void) didExitFullScreenVideoInAdView:(ATNativeADView*)adView placementID:(NSString*)placementID extra:(NSDictionary *)extra{
    NSLog(@"ATNativeViewController:: didExitFullScreenVideoInAdView:placementID:%@", placementID);
}

-(void) didTapCloseButtonInAdView:(ATNativeADView*)adView placementID:(NSString*)placementID extra:(NSDictionary *)extra {
    NSLog(@"ATNativeViewController:: didTapCloseButtonInAdView:placementID:%@ extra:%@", placementID, extra);
}

- (void)didCloseDetailInAdView:(ATNativeADView *)adView placementID:(NSString *)placementID extra:(NSDictionary *)extra {
    NSLog(@"ATNativeViewController:: didCloseDetailInAdView:placementID:%@ extra:%@", placementID, extra);
}

2.5 Other API

MethodDescription
getNativeValidAdsForPlacementID:Query the ad slot All cached information, the first item in the array is the advertising data to be displayed.
placementId: the advertising slot Id to be queried


// 查询该广告位的所有缓存信息
NSArray *array = [[ATAdManager sharedManager] getNativeValidAdsForPlacementID:@"your Native placementID"];
NSLog(@"ValidAds.count:%ld--- ValidAds:%@",array.count,array);

3. Sample code

ATNativeSelfRenderView.h

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


NS_ASSUME_NONNULL_BEGIN

@interface ATNativeSelfRenderView : UIView

@property(nonatomic, strong) UILabel *advertiserLabel;
@property(nonatomic, strong) UILabel *textLabel;
@property(nonatomic, strong) UILabel *titleLabel;
@property(nonatomic, strong) UILabel *ctaLabel;
@property(nonatomic, strong) UILabel *ratingLabel;
@property(nonatomic, strong) UIImageView *iconImageView;
@property(nonatomic, strong) UIImageView *mainImageView;
@property(nonatomic, strong) UIImageView *logoImageView;
@property(nonatomic, strong) UIButton *dislikeButton;

@property(nonatomic, strong) UIView *mediaView;

// only for yandex native
@property(nonatomic, strong) UILabel *domainLabel;
@property(nonatomic, strong) UILabel *warningLabel;

- (instancetype) initWithOffer:(ATNativeAdOffer *)offer;

@end

NS_ASSUME_NONNULL_END

ATNativeSelfRenderView.m

#import "ATNativeSelfRenderView.h"
#import <Masonry/Masonry.h>
#import <SDWebImage/SDWebImage.h>

@interface ATNativeSelfRenderView()

@property(nonatomic, strong) ATNativeAdOffer *nativeAdOffer;

@end


@implementation ATNativeSelfRenderView

- (instancetype) initWithOffer:(ATNativeAdOffer *)offer{

    if (self = [super init]) {
        
        _nativeAdOffer = offer;
        
        [self addView];
        [self makeConstraintsForSubviews];
        
        [self setupUI];
    }
    return self;
}

- (void)addView {
    self.advertiserLabel = [[UILabel alloc]init];
    self.advertiserLabel.font = [UIFont boldSystemFontOfSize:15.0f];
    self.advertiserLabel.textColor = [UIColor blackColor];
    self.advertiserLabel.textAlignment = NSTextAlignmentLeft;
    self.advertiserLabel.userInteractionEnabled = YES;
    [self addSubview:self.advertiserLabel];
        
    self.titleLabel = [[UILabel alloc]init];
    self.titleLabel.font = [UIFont boldSystemFontOfSize:18.0f];
    self.titleLabel.textColor = [UIColor blackColor];
    self.titleLabel.textAlignment = NSTextAlignmentLeft;
    self.titleLabel.userInteractionEnabled = YES;
    [self addSubview:self.titleLabel];
    
    self.textLabel = [[UILabel alloc]init];
    self.textLabel.font = [UIFont systemFontOfSize:15.0f];
    self.textLabel.textColor = [UIColor blackColor];
    self.textLabel.userInteractionEnabled = YES;
    [self addSubview:self.textLabel];
    
    self.ctaLabel = [[UILabel alloc]init];
    self.ctaLabel.font = [UIFont systemFontOfSize:15.0f];
    self.ctaLabel.textColor = [UIColor blackColor];
    self.ctaLabel.userInteractionEnabled = YES;

    [self addSubview:self.ctaLabel];

    self.ratingLabel = [[UILabel alloc]init];
    self.ratingLabel.font = [UIFont systemFontOfSize:15.0f];
    self.ratingLabel.textColor = [UIColor blackColor];
    self.ratingLabel.userInteractionEnabled = YES;
    [self addSubview:self.ratingLabel];
    
    self.domainLabel = [[UILabel alloc]init];
    self.domainLabel.font = [UIFont systemFontOfSize:15.0f];
    self.domainLabel.textColor = [UIColor blackColor];
    self.domainLabel.userInteractionEnabled = YES;
    [self addSubview:self.domainLabel];
    
    self.warningLabel = [[UILabel alloc]init];
    self.warningLabel.font = [UIFont systemFontOfSize:15.0f];
    self.warningLabel.textColor = [UIColor blackColor];
    self.warningLabel.userInteractionEnabled = YES;
    [self addSubview:self.warningLabel];
    
    self.iconImageView = [[UIImageView alloc]init];
    self.iconImageView.layer.cornerRadius = 4.0f;
    self.iconImageView.layer.masksToBounds = YES;
    self.iconImageView.contentMode = UIViewContentModeScaleAspectFit;
    self.iconImageView.userInteractionEnabled = YES;
    [self addSubview:self.iconImageView];
    
    self.mainImageView = [[UIImageView alloc]init];
    self.mainImageView.contentMode = UIViewContentModeScaleAspectFit;
    self.mainImageView.userInteractionEnabled = YES;
    [self addSubview:self.mainImageView];
    
    self.logoImageView = [[UIImageView alloc]init];
    self.logoImageView.contentMode = UIViewContentModeScaleAspectFit;
    self.logoImageView.userInteractionEnabled = YES;

    [self addSubview:self.logoImageView];
    
    self.dislikeButton = [UIButton buttonWithType:UIButtonTypeCustom];
    
    UIImage *closeImg = [UIImage imageNamed:@"icon_webview_close" inBundle:[NSBundle bundleWithPath:[[NSBundle mainBundle] pathForResource:@"AnyThinkSDK" ofType:@"bundle"]] compatibleWithTraitCollection:nil];
    self.dislikeButton = [UIButton buttonWithType:UIButtonTypeCustom];
    self.dislikeButton.backgroundColor = randomColor;
    [self.dislikeButton setImage:closeImg forState:0];
    [self addSubview:self.dislikeButton];
}

- (void)setupUI {
    if (self.nativeAdOffer.nativeAd.icon) {
        self.iconImageView.image = self.nativeAdOffer.nativeAd.icon;
    } else {
        [self.iconImageView sd_setImageWithURL:[NSURL URLWithString:self.nativeAdOffer.nativeAd.iconUrl]];
    }

    if (self.nativeAdOffer.nativeAd.mainImage) {
        self.mainImageView.image = self.nativeAdOffer.nativeAd.mainImage;
    } else {
        [self.mainImageView sd_setImageWithURL:[NSURL URLWithString:self.nativeAdOffer.nativeAd.imageUrl]];=
    }
    
    if (self.nativeAdOffer.nativeAd.logoUrl.length) {
        [self.logoImageView sd_setImageWithURL:[NSURL URLWithString:self.nativeAdOffer.nativeAd.logoUrl]];
    } else if (self.nativeAdOffer.nativeAd.logo) {
        self.logoImageView.image = self.nativeAdOffer.nativeAd.logo;
    } else { // All of these are nil, set the default platform logo using networkFirmID.
        if (self.nativeAdOffer.networkFirmID == 15) {//CSJ
            self.logoImageView.image = [UIImage imageNamed:@"tt_ad_logo_new"];
        }
    }
        
    self.advertiserLabel.text = self.nativeAdOffer.nativeAd.advertiser;
    self.titleLabel.text = self.nativeAdOffer.nativeAd.title;
    self.textLabel.text = self.nativeAdOffer.nativeAd.mainText;
    self.ctaLabel.text = self.nativeAdOffer.nativeAd.ctaText;
    
    // 仅yandex平台支持
    self.domainLabel.text = self.nativeAdOffer.nativeAd.domain;
    self.warningLabel.text = self.nativeAdOffer.nativeAd.warning;
}

-(void) makeConstraintsForSubviews {
    self.backgroundColor = randomColor;
    self.titleLabel.backgroundColor = randomColor;
    self.textLabel.backgroundColor = randomColor;
  
    [self.logoImageView mas_makeConstraints:^(MASConstraintMaker *make) {
        make.height.width.equalTo(@25);
        make.bottom.equalTo(self).equalTo(@-5);
        make.left.equalTo(self).equalTo(@5);
    }];
    
    [self.titleLabel mas_makeConstraints:^(MASConstraintMaker *make) {
        make.left.equalTo(self).offset(100);
        make.right.equalTo(self).offset(-40);
        make.height.equalTo(@20);
        make.top.equalTo(self).offset(20);
    }];
    
    [self.textLabel mas_makeConstraints:^(MASConstraintMaker *make) {
        make.left.equalTo(self).offset(100);
        make.right.equalTo(self).offset(-40);
        make.height.equalTo(@20);
        make.top.equalTo(self.titleLabel.mas_bottom).offset(10);
    }];
    
    [self.ctaLabel mas_makeConstraints:^(MASConstraintMaker *make) {
        make.top.equalTo(self.textLabel.mas_bottom).equalTo(@5);
        make.width.equalTo(@100);
        make.height.equalTo(@40);
        make.left.equalTo(self.textLabel.mas_left);
    }];
    
    [self.ratingLabel mas_makeConstraints:^(MASConstraintMaker *make) {
        make.left.equalTo(self.ctaLabel.mas_right).offset(20);
        make.height.equalTo(@40);
        make.top.equalTo(self.ctaLabel.mas_top).offset(0);
        make.width.equalTo(@20);
    }];
    
    [self.domainLabel mas_makeConstraints:^(MASConstraintMaker *make) {
        make.left.equalTo(self.ratingLabel.mas_right).offset(20);
        make.right.equalTo(self).offset(-40);
        make.top.equalTo(self.ctaLabel.mas_top).offset(0);
        make.height.equalTo(@40);
    }];
    
    [self.advertiserLabel mas_makeConstraints:^(MASConstraintMaker *make) {
        make.height.equalTo(@30);
        make.right.equalTo(self).equalTo(@-5);
        make.left.equalTo(self.ctaLabel.mas_right).offset(50);
        make.bottom.equalTo(self.iconImageView.mas_bottom);
    }];
    
    [self.iconImageView mas_makeConstraints:^(MASConstraintMaker *make) {
        make.left.equalTo(self).offset(20);
        make.height.width.equalTo(@75);
        make.top.equalTo(self).offset(20);
    }];
    
    [self.mainImageView mas_makeConstraints:^(MASConstraintMaker *make) {
        make.left.equalTo(self).offset(20);
        make.right.equalTo(self).offset(-20);
        make.top.equalTo(self.iconImageView.mas_bottom).offset(25);
        make.bottom.equalTo(self).offset(-5);
    }];

    [self.warningLabel mas_makeConstraints:^(MASConstraintMaker *make) {
        make.left.equalTo(self).offset(5);
        make.right.equalTo(self.mas_right).equalTo(@-5);
        make.bottom.equalTo(self).offset(-5);
        make.height.equalTo(@40);
    }];

    [self.dislikeButton mas_makeConstraints:^(MASConstraintMaker *make) {
        make.height.width.equalTo(@30);
        make.top.equalTo(self).equalTo(@5);
        make.right.equalTo(self.mas_right).equalTo(@-5);
    }];
}

@end

ATNativeSelfRenderViewController

#import "ATNativeSelfRenderViewController.h"

@interface ATNativeSelfRenderViewController()<ATNativeADDelegate>

@property (nonatomic) ATNativeADView *adView;
@property (nonatomic, strong) ATNativeSelfRenderView *nativeSelfRenderView;

@end

@implementation ATNativeSelfRenderViewController

- (void)viewDidLoad {
    [super viewDidLoad];
    [self loadAd];
}

- (void)loadAd {
    CGSize size = CGSizeMake(UIScreen.mainScreen.bounds.size.width, 350.0f);
    NSDictionary *extra = @{
        /* 
        Template AD size, through the advertising platform, the advertising platform will return a similar size of the optimal template AD, 
        if there is no specific size requirements, you can pass the height 0, by the platform adaptation width to return the appropriate height. 
        */
        kATExtraInfoNativeAdSizeKey:[NSValue valueWithCGSize:size]
    };
    [[ATAdManager sharedManager] loadADWithPlacementID:@"your Native placement id" extra:extra delegate:self];
}

- (void)entryAdScenario {
    /* To collect scene arrival rate statistics, you can view related information https://docs.toponad.com/#/zh-cn/ios/NetworkAccess/scenario/scenario 
    Call the "Enter AD scene" method when an AD trigger condition is met, such as: 
    ** The scenario is a pop-up AD after the cleanup, which is called at the end of the cleanup. 
    * 1、Call entryXXX to report the arrival of the scene. 
    * 2、Call xxRewardedVideoReadyForPlacementID. 
    * 3、Call showXX to show AD view. 
    * (Note the difference between auto and manual) */
    [[ATAdManager sharedManager] entryNativeScenarioWithPlacementID:@"your Native placement id" scene:@"your scenarioID"];
}

- (void)showAd {
 
    [self entryAdScenario];
    
    if ([[ATAdManager sharedManager] nativeAdReadyForPlacementID:@"your Native placement id"]) {
        ATNativeADConfiguration *config = [[ATNativeADConfiguration alloc] init];
        config.ADFrame = CGRectMake(.0f, 64.0f, CGRectGetWidth(self.view.bounds), 350.0f);
        // Here, as the default value, you can use [nativeADView getMediaView] in ATNativeADView to get mediaView for dynamic setting constraints.
        config.mediaViewFrame = CGRectMake(0, 150.0f, CGRectGetWidth(self.view.bounds), 350.0f - 150.0f);
        config.delegate = self;
        config.rootViewController = self;
        
        ATNativeAdOffer *offer = [[ATAdManager sharedManager]
                    getNativeAdOfferWithPlacementID:@"your Native placement id" scene:@"your scenarioID"];
        ATNativeSelfRenderView *selfRenderView = [[ATNativeSelfRenderView alloc] initWithOffer:offer];
        ATNativeADView *nativeADView = [[ATNativeADView alloc] initWithConfiguration:config currentOffer:offer placementID:@"your Native placement id"];

        UIView *mediaView = [nativeADView getMediaView];

     // Register the click event, it is best not to add the superview of the information flow as a whole to the click event,  
     // otherwise there may be a click close button, but also trigger the click information flow event.
        NSMutableArray *array = [@[selfRenderView.iconImageView] mutableCopy];
        if (mediaView) {
            [array addObject:mediaView];
            [selfRenderView addSubview:mediaView];
                
            [mediaView mas_updateConstraints:^(MASConstraintMaker *make) {
                make.left.right.bottom.equalTo(selfRenderView);
                make.top.equalTo(selfRenderView.mainImageView.mas_top);
            }];
        }
        [nativeADView registerClickableViewArray:array];

        // Bind a self-rendering view 
        // Assuming that a large image or video stream is not required, loadPrepareInfo does not need to assign values to mediaView and mainImageView.
        ATNativePrepareInfo *info = [ATNativePrepareInfo loadPrepareInfo:^(ATNativePrepareInfo * _Nonnull prepareInfo) {
            prepareInfo.textLabel = selfRenderView.textLabel;
            ......
        }];
        [nativeADView prepareWithNativePrepareInfo:info];

        [offer rendererWithConfiguration:config selfRenderView:selfRenderView nativeADView:nativeADView];
        [self.view addSubview:nativeADView];
    }
}

#pragma mark - delegate with loading
-(void) didFinishLoadingADWithPlacementID:(NSString *)placementID {
    NSLog(@"ATNativeViewController:: didFinishLoadingADWithPlacementID:%@", placementID);
}

-(void) didFailToLoadADWithPlacementID:(NSString *)placementID error:(NSError *)error {
    NSLog(@"ATNativeViewController:: didFailToLoadADWithPlacementID:%@ error:%@", placementID, error);
}

#pragma mark - delegate with native ad
-(void) didStartPlayingVideoInAdView:(ATNativeADView*)adView placementID:(NSString*)placementID extra:(NSDictionary *)extra{
    NSLog(@"ATNativeViewController:: didStartPlayingVideoInAdView:placementID:%@with extra: %@", placementID,extra);
}

-(void) didEndPlayingVideoInAdView:(ATNativeADView*)adView placementID:(NSString*)placementID extra:(NSDictionary *)extra{
    NSLog(@"ATNativeViewController:: didEndPlayingVideoInAdView:placementID:%@ extra: %@", placementID,extra);
}

-(void) didClickNativeAdInAdView:(ATNativeADView*)adView placementID:(NSString*)placementID extra:(NSDictionary *)extra{
    NSLog(@"ATNativeViewController:: didClickNativeAdInAdView:placementID:%@ with extra: %@", placementID,extra);
}

- (void) didDeepLinkOrJumpInAdView:(ATNativeADView *)adView placementID:(NSString *)placementID extra:(NSDictionary *)extra result:(BOOL)success {
    NSLog(@"ATNativeViewController:: didDeepLinkOrJumpInAdView:placementID:%@ with extra: %@, success:%@", placementID,extra, success ? @"YES" : @"NO");
}

-(void) didShowNativeAdInAdView:(ATNativeADView*)adView placementID:(NSString*)placementID extra:(NSDictionary *)extra{
    NSLog(@"ATNativeViewController:: didShowNativeAdInAdView:placementID:%@ with extra: %@", placementID,extra);
}

-(void) didEnterFullScreenVideoInAdView:(ATNativeADView*)adView placementID:(NSString*)placementID extra:(NSDictionary *)extra{
    NSLog(@"ATNativeViewController:: didEnterFullScreenVideoInAdView:placementID:%@", placementID);
}

-(void) didExitFullScreenVideoInAdView:(ATNativeADView*)adView placementID:(NSString*)placementID extra:(NSDictionary *)extra{
    NSLog(@"ATNativeViewController:: didExitFullScreenVideoInAdView:placementID:%@", placementID);
}

-(void) didTapCloseButtonInAdView:(ATNativeADView*)adView placementID:(NSString*)placementID extra:(NSDictionary *)extra {
    NSLog(@"ATNativeViewController:: didTapCloseButtonInAdView:placementID:%@ extra:%@", placementID, extra);
}

- (void)didCloseDetailInAdView:(ATNativeADView *)adView placementID:(NSString *)placementID extra:(NSDictionary *)extra {
    NSLog(@"ATNativeViewController:: didCloseDetailInAdView:placementID:%@ extra:%@", placementID, extra);
}

@end

Please refer to Demo's ATNativeSelfRenderViewController class

Last modified: 2025-05-30Powered by