ios – AdMob Native Ad Validator Ad Attribution missing


I am trying to integrate Native Ads from AdbMob in iOS with UIKit

Below is my code

import UIKit
import GoogleMobileAds

class ViewController: UIViewController,GADNativeAdLoaderDelegate,GADNativeAdDelegate,GADVideoControllerDelegate {
    
    private var adLoader: GADAdLoader!
    
    let adView: GADNativeAdView = {
        let view = GADNativeAdView()
        view.translatesAutoresizingMaskIntoConstraints = false
        view.backgroundColor = .white
                view.layer.cornerRadius = 10
                view.layer.shadowColor = UIColor.black.cgColor
                view.layer.shadowOpacity = 0.5
                view.layer.shadowOffset = CGSize(width: 0, height: 2)
        return view
    }()
    
    let adLabel: UILabel = {
        let label = UILabel()
        label.backgroundColor = UIColor(red: 1, green: 0.8, blue: 0.4, alpha: 1)
        label.font = UIFont.systemFont(ofSize: 15)
        label.textColor = UIColor.white
        label.text = "Ad"
        label.translatesAutoresizingMaskIntoConstraints = false
        return label
    }()

let iconImageView: UIImageView = {
        let imageView = UIImageView()
        imageView.backgroundColor = .cyan
        imageView.contentMode = .scaleAspectFit
        imageView.translatesAutoresizingMaskIntoConstraints = false
        return imageView
    }()
    
    let headlineLabel: UILabel = {
        let label = UILabel()
        label.font = UIFont.boldSystemFont(ofSize: 18)
        label.text = "Headline Label"
        label.translatesAutoresizingMaskIntoConstraints = false
        return label
    }()
    
    let advertiserLabel: UILabel = {
        let label = UILabel()
        label.font = UIFont.systemFont(ofSize: 14)
        label.text = "Advertiser Label"
        label.translatesAutoresizingMaskIntoConstraints = false
        return label
    }()
    
    let ratingsImageView: UIImageView = {
        let imageView = UIImageView()
        imageView.contentMode = .scaleAspectFit
        imageView.translatesAutoresizingMaskIntoConstraints = false
        return imageView
    }()
    
    let bodyLabel: UILabel = {
        let label = UILabel()
        label.font = UIFont.systemFont(ofSize: 14)
        label.text = "This is the body of the card."
        label.numberOfLines = 0
        label.translatesAutoresizingMaskIntoConstraints = false
        return label
    }()
    
    let gadMediaView: GADMediaView = {
        let view = GADMediaView()
        view.translatesAutoresizingMaskIntoConstraints = false
        return view
    }()
    
    let installButton: UIButton = {
        let button = UIButton()
        button.backgroundColor = .systemBlue
        button.setTitle("Install", for: .normal)
        button.titleLabel?.font = UIFont.boldSystemFont(ofSize: 16)
        button.translatesAutoresizingMaskIntoConstraints = false
        return button
    }()
    
    let storeLabel: UILabel = {
        let label = UILabel()
        label.text = "Store"
        label.font = UIFont.systemFont(ofSize: 14)
        label.translatesAutoresizingMaskIntoConstraints = false
        return label
    }()
    
    let priceLabel: UILabel = {
        let label = UILabel()
        label.text = "Price"
        label.font = UIFont.systemFont(ofSize: 14)
        label.translatesAutoresizingMaskIntoConstraints = false
        return label
    }()
    
    
    override func viewDidLoad() {
        super.viewDidLoad()
        // Do any additional setup after loading the view.
        
        setupConstraints()
        
        let multipleAdOptions = GADMultipleAdsAdLoaderOptions()
        multipleAdOptions.numberOfAds = 5;
        
        adLoader = GADAdLoader(adUnitID: "ca-app-pub-3940256099942544/3986624511",
                               rootViewController: self,
                               adTypes: [.native],
                               options: nil)
        adLoader.delegate = self
        adLoader.load(GADRequest())
        
    }
    
    func setupConstraints() {
        // Constraints for your custom GADUnifiedNativeAdView
        view.addSubview(adView)
        adView.addSubview(adLabel)
        adView.addSubview(iconImageView)
        adView.addSubview(headlineLabel)
        adView.addSubview(advertiserLabel)
        adView.addSubview(ratingsImageView)
        adView.addSubview(bodyLabel)
        adView.addSubview(gadMediaView)
        adView.addSubview(installButton)
        adView.addSubview(storeLabel)
        adView.addSubview(priceLabel)
        
        NSLayoutConstraint.activate([
            adView.leadingAnchor.constraint(equalTo: view.leadingAnchor, constant: 16),
            adView.trailingAnchor.constraint(equalTo: view.trailingAnchor, constant: -16),
            adView.topAnchor.constraint(equalTo: view.safeAreaLayoutGuide.topAnchor),
            adView.heightAnchor.constraint(equalToConstant: 350)
        ])
        
        NSLayoutConstraint.activate([
            adLabel.topAnchor.constraint(equalTo: adView.topAnchor,constant: 4),
            adLabel.leadingAnchor.constraint(equalTo: adView.leadingAnchor,constant: 4),
            adLabel.heightAnchor.constraint(equalToConstant: 30), // Set a specific height for the title label
            adLabel.widthAnchor.constraint(equalToConstant: 30)
        ])
        
        
        NSLayoutConstraint.activate([
            iconImageView.topAnchor.constraint(equalTo: adLabel.bottomAnchor, constant: 8),
            iconImageView.leadingAnchor.constraint(equalTo: adLabel.trailingAnchor, constant: 8),
            iconImageView.widthAnchor.constraint(equalToConstant: 40),
            iconImageView.heightAnchor.constraint(equalToConstant: 40)
        ])
        
        NSLayoutConstraint.activate([
            headlineLabel.leadingAnchor.constraint(equalTo: iconImageView.trailingAnchor, constant: 8),
            headlineLabel.topAnchor.constraint(equalTo: iconImageView.topAnchor)
        ])
        
        NSLayoutConstraint.activate([
            advertiserLabel.leadingAnchor.constraint(equalTo: iconImageView.trailingAnchor, constant: 8),
            advertiserLabel.topAnchor.constraint(equalTo: headlineLabel.bottomAnchor, constant: 2),
            
        ])
        
        NSLayoutConstraint.activate([
            ratingsImageView.leadingAnchor.constraint(equalTo: advertiserLabel.trailingAnchor, constant: 8),
            ratingsImageView.topAnchor.constraint(equalTo: advertiserLabel.bottomAnchor),
            ratingsImageView.widthAnchor.constraint(equalToConstant: 100),
            ratingsImageView.heightAnchor.constraint(equalToConstant: 17)
        ])
        
        NSLayoutConstraint.activate([
            bodyLabel.topAnchor.constraint(equalTo: iconImageView.bottomAnchor, constant: 8),
            bodyLabel.leadingAnchor.constraint(equalTo: adView.leadingAnchor),
            bodyLabel.trailingAnchor.constraint(equalTo: adView.trailingAnchor)
        ])
        
        NSLayoutConstraint.activate([
            gadMediaView.leadingAnchor.constraint(equalTo: adView.leadingAnchor, constant: 10),
            gadMediaView.trailingAnchor.constraint(equalTo: adView.trailingAnchor, constant: -10),
            gadMediaView.topAnchor.constraint(equalTo: bodyLabel.bottomAnchor, constant: 8),
            gadMediaView.heightAnchor.constraint(equalToConstant: 150)
        ])
        
        NSLayoutConstraint.activate([
            installButton.trailingAnchor.constraint(equalTo: adView.trailingAnchor, constant: -10),
            installButton.topAnchor.constraint(equalTo: gadMediaView.bottomAnchor,constant: 10),
            installButton.heightAnchor.constraint(equalToConstant: 40),
            installButton.widthAnchor.constraint(equalToConstant: 100)
        ])
        
        NSLayoutConstraint.activate([
            storeLabel.trailingAnchor.constraint(equalTo: installButton.leadingAnchor, constant: -10),
            storeLabel.centerYAnchor.constraint(equalTo: installButton.centerYAnchor)
        ])
        
        NSLayoutConstraint.activate([
            priceLabel.trailingAnchor.constraint(equalTo: storeLabel.leadingAnchor, constant: -10),
            priceLabel.centerYAnchor.constraint(equalTo: storeLabel.centerYAnchor)
        ])
    }
    
    func adLoader(_ adLoader: GADAdLoader, didReceive nativeAd: GADNativeAd) {
        nativeAd.delegate = self
        
        iconImageView.image = nativeAd.icon?.image
        
        
        headlineLabel.text = nativeAd.headline
        gadMediaView.mediaContent = nativeAd.mediaContent
        let mediaContent = nativeAd.mediaContent
        if mediaContent.hasVideoContent {
            // By acting as the delegate to the GADVideoController, this ViewController receives messages
            // about events in the video lifecycle.
            mediaContent.videoController.delegate = self
            print("Ad contains a video asset.")
        } else {
            print("Ad does not contain a video.")
        }
        bodyLabel.text = nativeAd.body
        advertiserLabel.text = nativeAd.advertiser
        installButton.setTitle(nativeAd.callToAction, for: .normal)
        
        storeLabel.text = nativeAd.store
        priceLabel.text = nativeAd.price
        
        // In order for the SDK to process touch events properly, user interaction should be disabled.
        installButton.isUserInteractionEnabled = false
        ratingsImageView.image = imageOfStars(from: nativeAd.starRating)
        
        adView.nativeAd = nativeAd
    }
    
    func imageOfStars(from starRating: NSDecimalNumber?) -> UIImage? {
      guard let rating = starRating?.doubleValue else {
        return nil
      }
      if rating >= 5 {
        return UIImage(named: "stars_5")
      } else if rating >= 4.5 {
        return UIImage(named: "stars_4_5")
      } else if rating >= 4 {
        return UIImage(named: "stars_4")
      } else if rating >= 3.5 {
        return UIImage(named: "stars_3_5")
      } else {
        return nil
      }
    }
    
    func adLoader(_ adLoader: GADAdLoader, didFailToReceiveAdWithError error: Error) {
        print("\(adLoader) failed with error: \(error.localizedDescription)")
    }
    
    func adLoaderDidFinishLoading(_ adLoader: GADAdLoader) {
        
    }
    
    func nativeAdDidRecordImpression(_ nativeAd: GADNativeAd) {
        // The native ad was shown.
    }
    
    func nativeAdDidRecordClick(_ nativeAd: GADNativeAd) {
        // The native ad was clicked on.
    }
    
    func nativeAdWillPresentScreen(_ nativeAd: GADNativeAd) {
        // The native ad will present a full screen view.
    }
    
    func nativeAdWillDismissScreen(_ nativeAd: GADNativeAd) {
        // The native ad will dismiss a full screen view.
    }
    
    func nativeAdDidDismissScreen(_ nativeAd: GADNativeAd) {
        // The native ad did dismiss a full screen view.
    }
    
    func nativeAdWillLeaveApplication(_ nativeAd: GADNativeAd) {
        // The native ad will cause the app to become inactive and
        // open a new app.
    }
    
    
    func videoControllerDidEndVideoPlayback(_ videoController: GADVideoController) {
        print("Video playback has ended.")
    }
}

Below is the output

enter image description here

I keep getting a validation error saying Ad attribution missing but I have added the a UILabel saying Ad at top left corner but still same validation error

This is the issue it points to

enter image description here

What else needs to be added

After going through this doc, it also says I need to add an image on top right corner, I tried adding a dummy image, I couldn’t find the exact image of Ads by Google Icon which is pointed in docs but still same issue

Latest articles

spot_imgspot_img

Related articles

Leave a reply

Please enter your comment!
Please enter your name here

spot_imgspot_img