Native ads

Native ads are an ad format where the appearance of ads can be determined on the app side. Use this feature to adjust the visual style and placement of ads so that they match the design of your app.

Note

Examples showing how all the format types work are available in the demo project.

Entity

Description

onAdFailedToLoad

If onAdFailedToLoad() returns an error, don't attempt to load a new ad again using the same method.

NativeAdRequestConfiguration

In request parameters, you can specify the ad unit ID (RM-id), image loading method, age, gender, and other data that can make impressions more relevant. To learn more, see Ad targeting.

adUnitId

Use:

  • Development mode to work with demo ad units.

  • Production mode to work with R-M-XXXXXX-Y (for the actual ID, check the Yandex Advertising Network interface). R-M-XXXXXX-Y is a template for your actual ad unit ID that will be used to receive various creatives.

Example of creating a native ad

Define the CustomNative class and create NativeAdView.xml:

class CustomNativeAdActivity : AppCompatActivity(), NativeAdEventListener {

    private val nativeAdView get() = binding.nativeAd.root
    private val additionalContainer get() = binding.additionalContainer
    private val adUnitId = "demo-native-app-yandex" // Use R-M-XXXXXX-Y or demo-block (look for the description below)
    private var nativeAdLoader: NativeAdLoader? = null
    private lateinit var binding: ActivityCustomNativeAdBinding

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        binding = ActivityCustomNativeAdBinding.inflate(layoutInflater)
        binding.btnShowBanner.setOnClickListener {
            loadNative()
        }
        setContentView(binding.root)
    }

    private fun loadNative() {
        createNative()
        additionalContainer.removeAllViews()
        nativeAdView.isVisible = false
        nativeAdLoader?.loadAd(buildAdRequestConfiguration())
    }

    private fun createNative() {
        nativeAdLoader = NativeAdLoader(this).apply {
            setNativeAdLoadListener(object : NativeAdLoadListener {
                override fun onAdLoaded(ad: NativeAd) {
                    bindNative(ad)
                }
                override fun onAdFailedToLoad(error: AdRequestError) {}
            })
        }
    }

    private fun buildAdRequestConfiguration(): NativeAdRequestConfiguration {
        return NativeAdRequestConfiguration
            .Builder(adUnitId)
            .setShouldLoadImagesAutomatically(true)
            .build()
    }

    private fun bindNative(nativeAd: NativeAd) {
        val nativeAdViewBinder = binding.nativeAd.run {
            NativeAdViewBinder.Builder(nativeAdView)
                .setAgeView(age)
                .setBodyView(body)
                .setCallToActionView(callToAction)
                .setDomainView(domain)
                .setFaviconView(favicon)
                .setFeedbackView(feedback)
                .setIconView(icon)
                .setMediaView(media)
                .setPriceView(price)
                .setRatingView(rating)
                .setReviewCountView(reviewCount)
                .setSponsoredView(sponsored)
                .setTitleView(title)
                .setWarningView(warning)
                .build()
        }

        try {
            nativeAd.bindNativeAd(nativeAdViewBinder)
            nativeAd.info?.let { processAdditionalText(it) }
            nativeAd.setNativeAdEventListener(this@CustomNativeAdActivity)
            nativeAdView.isVisible = true
        } catch (exception: NativeAdException) {
            println("Error binding native ad: ${exception.message}")
        }
    }

    private fun processAdditionalText(rawJson: String) {
        try {
            val jsonObject = JSONObject(rawJson)
            val contentJSONArray = jsonObject.getJSONArray("content")

            repeat(contentJSONArray.length()) { index ->
                val elementName = contentJSONArray.getString(index)
                val elementConfiguration = jsonObject.getJSONObject(elementName)

                when (elementName) {
                    "text" -> addTextToLayout(elementConfiguration, index)
                    "button" -> addButtonToLayout(elementConfiguration, index)
                }
            }
        } catch (e: JSONException) {
            println("Error processing additional text: ${e.message}")
        }
    }

    private fun addTextToLayout(textConfiguration: JSONObject, index: Int) {
        val textView = TextView(this).apply {
            setPadding(16)
            text = textConfiguration.getString("value")
        }
        additionalContainer.addView(textView, index)
    }

    private fun addButtonToLayout(buttonConfiguration: JSONObject, index: Int) {
        val buttonView = Button(this).apply {
            setPadding(16)
            text = buttonConfiguration.getString("label")
            val colorHex = buttonConfiguration.getString("backgroundColor")
            setBackgroundColor(Color.parseColor(colorHex))
            setOnClickListener {
                val link = buttonConfiguration.getString("link")
                val intent = Intent(Intent.ACTION_VIEW, Uri.parse(link))
                startActivity(intent)
            }
        }
        additionalContainer.addView(buttonView, index)
    }

    override fun onDestroy() {
        nativeAdLoader?.setNativeAdLoadListener(null)
        nativeAdLoader = null
        super.onDestroy()
    }

    override fun onAdClicked() {}
    override fun onImpression(impressionData: ImpressionData?) {}
    override fun onLeftApplication() {}
    override fun onReturnedToApplication() {}
}
public class CustomNativeAdActivity extends AppCompatActivity implements NativeAdEventListener {

    private ActivityCustomNativeAdBinding binding;
    private NativeAdLoader nativeAdLoader;
    private NativeAdViewBinder nativeAdViewBinder;

    private final String adUnitId = "demo-native-app-yandex"; // Use R-M-XXXXXX-Y or demo-block (look for the description below)

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        binding = ActivityCustomNativeAdBinding.inflate(getLayoutInflater());
        setContentView(binding.getRoot());

        binding.btnShowBanner.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                loadNative();
            }
        });
    }

    private void loadNative() {
        createNative();
        binding.additionalContainer.removeAllViews();
        binding.nativeAd.getRoot().setVisibility(View.GONE);
        if (nativeAdLoader != null) {
            nativeAdLoader.loadAd(buildAdRequestConfiguration());
        }
    }

    private void createNative() {
        nativeAdLoader = new NativeAdLoader(this);
        nativeAdLoader.setNativeAdLoadListener(new NativeAdLoadListener() {
            @Override
            public void onAdLoaded(NativeAd ad) {
                bindNative(ad);
            }
            @Override
            public void onAdFailedToLoad(AdRequestError error) {}
        });
    }

    private NativeAdRequestConfiguration buildAdRequestConfiguration() {
        return new NativeAdRequestConfiguration.Builder(adUnitId)
                .setShouldLoadImagesAutomatically(true)
                .build();
    }

    private void bindNative(NativeAd nativeAd) {
        NativeAdLayoutBinding adBinding = binding.nativeAd;

        // Manual binding creation (or if ViewBinding is auto-generated)
        nativeAdViewBinder = new NativeAdViewBinder.Builder(adBinding.getRoot())
                .setAgeView(adBinding.age)
                .setBodyView(adBinding.body)
                .setCallToActionView(adBinding.callToAction)
                .setDomainView(adBinding.domain)
                .setFaviconView(adBinding.favicon)
                .setFeedbackView(adBinding.feedback)
                .setIconView(adBinding.icon)
                .setMediaView(adBinding.media)
                .setPriceView(adBinding.price)
                .setRatingView(adBinding.rating)
                .setReviewCountView(adBinding.reviewCount)
                .setSponsoredView(adBinding.sponsored)
                .setTitleView(adBinding.title)
                .setWarningView(adBinding.warning)
                .build();

        try {
            nativeAd.bindNativeAd(nativeAdViewBinder);
            String infoJson = nativeAd.getInfo();
            if (infoJson != null) {
                processAdditionalText(infoJson);
            }
            nativeAd.setNativeAdEventListener(this);
            adBinding.getRoot().setVisibility(View.VISIBLE);
        } catch (NativeAdException exception) {
            System.out.println("Error binding native ad: " + exception.getMessage());
        }
    }

    private void processAdditionalText(String rawJson) {
        try {
            JSONObject jsonObject = new JSONObject(rawJson);
            JSONArray contentJSONArray = jsonObject.getJSONArray("content");
            for (int i = 0; i < contentJSONArray.length(); ++i) {
                String elementName = contentJSONArray.getString(i);
                JSONObject elementConfiguration = jsonObject.getJSONObject(elementName);
                switch (elementName) {
                    case "text":
                        addTextToLayout(elementConfiguration, i);
                        break;
                    case "button":
                        addButtonToLayout(elementConfiguration, i);
                        break;
                }
            }
        } catch (JSONException e) {
            System.out.println("Error processing additional text: " + e.getMessage());
        }
    }

    private void addTextToLayout(JSONObject textConfiguration, int index) {
        TextView textView = new TextView(this);
        textView.setPadding(16, 16, 16, 16);
        try {
            textView.setText(textConfiguration.getString("value"));
        } catch (JSONException ignored) { }
        binding.additionalContainer.addView(textView, index);
    }

    private void addButtonToLayout(final JSONObject buttonConfiguration, int index) {
        Button buttonView = new Button(this);
        buttonView.setPadding(16, 16, 16, 16);
        try {
            buttonView.setText(buttonConfiguration.getString("label"));
            String colorHex = buttonConfiguration.getString("backgroundColor");
            buttonView.setBackgroundColor(Color.parseColor(colorHex));
            buttonView.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View v) {
                    try {
                        String link = buttonConfiguration.getString("link");
                        Intent intent = new Intent(Intent.ACTION_VIEW, Uri.parse(link));
                        startActivity(intent);
                    } catch (JSONException ignored) { }
                }
            });
        } catch (JSONException ignored) { }
        binding.additionalContainer.addView(buttonView, index);
    }

    @Override
    protected void onDestroy() {
        if (nativeAdLoader != null) {
            nativeAdLoader.setNativeAdLoadListener(null);
            nativeAdLoader = null;
        }
        super.onDestroy();
    }
    @Override
    public void onAdClicked() {}
    @Override
    public void onImpression(@Nullable ImpressionData impressionData) {}
    @Override
    public void onLeftApplication() {}
    @Override
    public void onReturnedToApplication() {}
}
<androidx.constraintlayout.widget.ConstraintLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:id="@+id/coordinatorLayout"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".CustomNativeAdActivity">

    <Button
        android:id="@+id/btnShowBanner"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Load NativeAd"
        app:layout_constraintLeft_toLeftOf="parent"
        app:layout_constraintRight_toRightOf="parent"
        app:layout_constraintTop_toTopOf="parent"
        app:layout_constraintBottom_toBottomOf="parent" />

    <include
        android:id="@+id/native_ad"
        layout="@layout/native_ad_view"
        android:layout_width="match_parent"
        android:layout_height="0dp"
        android:visibility="gone"
        app:layout_constraintVertical_weight="1"
        app:layout_constraintBottom_toTopOf="@+id/additional_container"/>

    <LinearLayout
        android:id="@+id/additional_container"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:orientation="vertical"
        app:layout_constraintBottom_toBottomOf="parent" />

</androidx.constraintlayout.widget.ConstraintLayout>
<com.yandex.mobile.ads.nativeads.NativeAdView
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:id="@+id/native_ad_container"
    android:layout_width="match_parent"
    android:layout_height="wrap_content">

    <androidx.constraintlayout.widget.ConstraintLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:layout_marginStart="8dp"
        android:layout_marginTop="8dp"
        android:layout_marginEnd="8dp"
        android:layout_marginBottom="4dp">

        <androidx.constraintlayout.widget.Group
            android:id="@+id/components"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            app:constraint_referenced_ids="age,sponsored,feedback,title" />

        <TextView
            android:id="@+id/age"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:maxLines="1"
            android:textColor="#7f7f7f"
            app:layout_constraintBottom_toTopOf="@id/barrier_top"
            app:layout_constraintEnd_toStartOf="@id/sponsored"
            app:layout_constraintHorizontal_chainStyle="spread_inside"
            app:layout_constraintStart_toStartOf="parent"
            app:layout_constraintTop_toTopOf="parent"
            tools:text="18+"
            tools:visibility="visible" />

        <TextView
            android:id="@+id/sponsored"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:maxLines="1"
            android:textColor="#7f7f7f"
            android:textSize="11sp"
            app:layout_constraintBottom_toTopOf="@id/barrier_top"
            app:layout_constraintEnd_toStartOf="@id/feedback"
            app:layout_constraintStart_toEndOf="@id/age"
            app:layout_constraintTop_toTopOf="parent"
            tools:text="Yandex.Direct"
            tools:visibility="visible" />

        <androidx.appcompat.widget.AppCompatImageView
            android:id="@+id/feedback"
            android:layout_width="16dp"
            android:layout_height="16dp"
            app:layout_constraintBottom_toTopOf="@id/barrier_top"
            android:src="@drawable/close_button"
            app:layout_constraintEnd_toEndOf="parent"
            app:layout_constraintStart_toEndOf="@id/sponsored"
            app:layout_constraintTop_toTopOf="parent"
            tools:visibility="visible" />

        <androidx.constraintlayout.widget.Barrier
            android:id="@+id/barrier_top"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            app:barrierDirection="bottom"
            app:constraint_referenced_ids="age,sponsored,feedback" />

        <ImageView
            android:id="@+id/icon"
            android:layout_width="80dp"
            android:layout_height="80dp"
            android:adjustViewBounds="true"
            android:scaleType="centerCrop"
            android:layout_marginTop="4dp"
            android:layout_marginEnd="8dp"
            android:layout_marginRight="8dp"
            app:layout_constraintStart_toStartOf="parent"
            app:layout_constraintBottom_toTopOf="@id/barrier_body"
            app:layout_constraintEnd_toStartOf="@id/barrier_icon"
            app:layout_constraintTop_toBottomOf="@id/barrier_top"
            tools:visibility="visible" />

        <TextView
            android:id="@+id/title"
            android:layout_width="0dp"
            android:layout_height="wrap_content"
            android:layout_marginTop="4dp"
            android:maxLines="2"
            android:textSize="15sp"
            style="@style/TextAppearance.Material3.TitleSmall"
            app:layout_constraintBottom_toTopOf="@id/body"
            app:layout_constraintEnd_toEndOf="parent"
            app:layout_constraintStart_toEndOf="@id/barrier_icon"
            app:layout_constraintTop_toBottomOf="@id/barrier_top"
            app:layout_constraintVertical_chainStyle="packed"
            tools:text="Yandex.Browser for iPhone and Android"
            tools:visibility="visible" />

        <TextView
            android:id="@+id/body"
            android:layout_width="0dp"
            android:layout_height="wrap_content"
            android:maxLines="3"
            android:textSize="13sp"
            style="@style/TextAppearance.Material3.BodySmall"
            app:layout_constraintBottom_toTopOf="@id/barrier_domain"
            app:layout_constraintEnd_toEndOf="parent"
            app:layout_constraintStart_toEndOf="@id/barrier_icon"
            app:layout_constraintTop_toBottomOf="@id/title"
            tools:text="Your bookmarks and favorite sites are available to you on any device with Yandex.Browser. You will never lose them, even if you lose your device or break it."
            tools:visibility="visible" />

        <ImageView
            android:id="@+id/favicon"
            android:layout_width="16dp"
            android:layout_height="16dp"
            android:layout_marginEnd="4dp"
            android:layout_marginRight="4dp"
            android:adjustViewBounds="true"
            android:scaleType="centerCrop"
            app:layout_constraintBottom_toTopOf="@id/barrier_domain"
            app:layout_constraintEnd_toStartOf="@id/domain"
            app:layout_constraintHorizontal_bias="0"
            app:layout_constraintHorizontal_chainStyle="packed"
            app:layout_constraintStart_toEndOf="@id/barrier_icon"
            app:layout_constraintTop_toBottomOf="@id/body"
            tools:visibility="visible" />

        <androidx.constraintlayout.widget.Barrier
            android:id="@+id/barrier_domain"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            app:barrierDirection="top"
            app:constraint_referenced_ids="domain,favicon" />

        <TextView
            android:id="@+id/domain"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:maxLines="1"
            android:textColor="#7f7f7f"
            android:textSize="13sp"
            app:layout_constraintEnd_toEndOf="parent"
            app:layout_constraintBottom_toTopOf="@id/barrier_body"
            app:layout_constraintHorizontal_bias="0"
            app:layout_constraintStart_toEndOf="@id/favicon"
            app:layout_constraintTop_toBottomOf="@id/body"
            tools:text="https://browser.yandex.com"
            tools:visibility="visible" />

        <androidx.constraintlayout.widget.Barrier
            android:id="@+id/barrier_body"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            app:barrierDirection="bottom"
            app:constraint_referenced_ids="title,icon,body,domain,favicon" />

        <TextView
            android:id="@+id/price"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_marginTop="8dp"
            app:layout_constraintBottom_toTopOf="@id/rating"
            app:layout_constraintEnd_toStartOf="@id/barrier_rating"
            app:layout_constraintHorizontal_bias="0"
            app:layout_constraintStart_toEndOf="@id/barrier_icon"
            app:layout_constraintTop_toBottomOf="@id/barrier_body"
            tools:text="Free"
            tools:visibility="visible" />

        <com.example.myapplication.RatingView
            android:id="@+id/rating"
            style="?android:attr/ratingBarStyleSmall"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_marginEnd="8dp"
            android:layout_marginRight="8dp"
            android:layout_marginBottom="4dp"
            android:numStars="5"
            android:stepSize="0.5"
            app:layout_constraintBottom_toTopOf="@id/review_count"
            app:layout_constraintEnd_toStartOf="@id/barrier_rating"
            app:layout_constraintHorizontal_chainStyle="spread_inside"
            app:layout_constraintStart_toEndOf="@id/barrier_icon"
            app:layout_constraintTop_toBottomOf="@id/price"
            tools:visibility="visible" />

        <TextView
            android:id="@+id/review_count"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:ellipsize="end"
            android:maxLines="1"
            android:textColor="#7f7f7f"
            android:textSize="13sp"
            app:layout_constraintBottom_toTopOf="@id/barrier_footer"
            app:layout_constraintEnd_toStartOf="@id/barrier_rating"
            app:layout_constraintHorizontal_bias="0"
            app:layout_constraintStart_toEndOf="@id/barrier_icon"
            app:layout_constraintTop_toBottomOf="@id/rating"
            tools:text="review count"
            tools:visibility="visible" />

        <androidx.constraintlayout.widget.Barrier
            android:id="@+id/barrier_icon"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            app:barrierDirection="end"
            app:constraint_referenced_ids="icon" />

        <androidx.constraintlayout.widget.Barrier
            android:id="@+id/barrier_rating"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            app:barrierDirection="end"
            app:constraint_referenced_ids="rating,price,review_count" />

        <Button
            android:id="@+id/call_to_action"
            style="@style/Widget.AppCompat.Button.Borderless"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:background="@drawable/call_to_action_background"
            android:maxLines="1"
            android:minHeight="36dp"
            android:textAllCaps="false"
            android:textSize="13sp"
            app:layout_constraintBottom_toTopOf="@id/barrier_footer"
            app:layout_constraintEnd_toEndOf="parent"
            app:layout_constraintStart_toEndOf="@id/barrier_rating"
            app:layout_constraintTop_toBottomOf="@id/barrier_body"
            app:layout_constraintHorizontal_bias="1"
            app:layout_constraintVertical_bias="1"
            tools:text="Install"
            tools:visibility="visible" />

        <androidx.constraintlayout.widget.Barrier
            android:id="@+id/barrier_footer"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            app:barrierDirection="bottom"
            app:constraint_referenced_ids="price,domain,call_to_action,review_count" />

        <com.yandex.mobile.ads.nativeads.MediaView
            android:id="@+id/media"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            app:layout_constrainedHeight="true"
            app:layout_constrainedWidth="true"
            android:layout_marginTop="4dp"
            android:layout_marginBottom="4dp"
            app:layout_constraintEnd_toEndOf="parent"
            app:layout_constraintStart_toStartOf="parent"
            app:layout_constraintTop_toBottomOf="@id/barrier_footer"
            app:layout_constraintBottom_toTopOf="@id/warning"
            tools:visibility="visible" />

        <TextView
            android:id="@+id/warning"
            android:layout_width="0dp"
            android:layout_height="wrap_content"
            android:background="#f5f5f5"
            android:paddingLeft="8dp"
            android:paddingTop="4dp"
            android:paddingRight="8dp"
            android:textColor="#7f7f7f"
            android:textSize="13sp"
            app:layout_constraintBottom_toBottomOf="parent"
            app:layout_constraintEnd_toEndOf="parent"
            app:layout_constraintStart_toStartOf="parent"
            app:layout_constraintTop_toBottomOf="@id/media"
            android:visibility="gone"
            tools:text="We strongly recommend avoiding this type of website and not clicking the Ignore this warning button!"
            tools:visibility="visible" />
    </androidx.constraintlayout.widget.ConstraintLayout>
</com.yandex.mobile.ads.nativeads.NativeAdView>

Checking integration

Build and run your project. You can check if the integration is successful by searching the YandexAds keyword in Logcat:

[Integration] Ad type native was integrated successfully