Login
Welcome
Login

InRead - Webview Integration

This page explains how to integrate the Teads inApp SDK in application using WebView to display content.

If you are not using a WebView, I.e. If the content is display using native components, please follow the Standard integration documentation.

  1. Webview integration basics
  2. Prerequisites
  3. Implementation
  4. Event Monitoring
  5. Configuration Changes
  6. Brand Safety and web content URL
  7. Check list
  8. Additional settings

The Teads Standard JavaScript Tag used for classic web integration cannot be used for the inApp context (WebView containers included).

WebViews are powerful components that allows Android applications to display content from the web directly inside an application.

Even though JavaScript can be executed, WebViews are sandboxed containers isolating the Teads Standard JavaScript Tag from contextual data breaking features such as brand safety, viewability measurement, fraud detection, dynamic creatives, etc.

These limitations make the Teads inApp SDK the only way to safely deliver Teads ads in app context.

Webview integration basics

The Teads inApp SDK will open a blank slot inside the article HTML at the location you'll define.
A view component is created over the blank space and will contain the ad.
This view is synchronized with the user scroll creating the illusion of the player inside the article.

As we can't choose the player position in the article, this integration requires a custom setup on your side. We do propose a "helper file" that helps in this step (see prerequisites section)

Please note, as each app is differently shaped, we do encourage you to customize the "helper file" to match your own needs.
Due to its customizable nature, this Helper file is not included in the SDK package, but downloadable separately

Prerequisites

Important

WebView integrations are too tied to your code architecture, pattern and framework.
Unfortunately, there is no universal way to fit all WebView integrations.

The proposed "Helper" is a generic module meant to help you tailor the integration to your basic needs.
Please note you might need to adapt and complete it since it does not cover all situations.
Hence, these files are not included in the SDK package.
Please, keep in mind we might update it from time to time outside the SDK release cycle.

Implementation

The article is using the landscape test PID 84242. This PID is meant for testing purpose and shall not be released into production.

Please retrieve your production PID from your local account manager.

First, The WebView used should be an instance of the ObservableWebView copied in the prerequisite part.

<com.your.app.ObservableWebView
    android:id="@+id/webview"
    android:layout_width="match_parent"
    android:layout_height="match_parent" />

Then, create a new InReadAdPlacement and SyncAdWebView and load your webview content with a CustomInReadWebviewClient

class InReadWebViewFragment : BaseFragment(), SyncAdWebView.Listener {

    private lateinit var webviewHelperSynch: SyncAdWebView
    private lateinit var adPlacement: InReadAdPlacement

    override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?,
                              savedInstanceState: Bundle?): View? {
        return inflater.inflate(R.layout.fragment_inread_webview, container, false)
    }

    @SuppressLint("SetJavaScriptEnabled")
    override fun onViewCreated(rootView: View, savedInstanceState: Bundle?) {
        val placementSettings = AdPlacementSettings.Builder()
                .enableDebug()
                .build()

        adPlacement = TeadsSDK.createInReadPlacement(requireActivity(), pid, placementSettings)

        webviewHelperSynch = SyncAdWebView(requireContext(), webview, this@InReadWebViewFragment, "#teads-placement-slot")

        webview.settings.javaScriptEnabled = true
        webview.webViewClient = CustomInReadWebviewClient(webviewHelperSynch, getTitle())
        webview.loadUrl("https://example.com/article_1")
    }
}

Implement SyncWebViewTeadsAdView.Listener to load the ad after the WebView is ready to receive one

override fun onHelperReady(adContainer: ViewGroup) {
    val requestSettings = AdRequestSettings.Builder()
                .pageSlotUrl("https://example.com/article_1")
                .build()

    adPlacement.requestAd(requestSettings, object : InReadAdListener {
        override fun adOpportunityTrackerView(trackerView: AdOpportunityTrackerView) {
            // register the AdOpportunityTrackerView inside the webview ad container
            webviewHelperSynch.registerTrackerView(trackerView)
        }

        override fun onAdReceived(inReadAdView: InReadAdView, adRatio: AdRatio) {
            // register the InReadAdView inside the webview ad container and will open the slot with specified ratio
            webviewHelperSynch.registerAdView(inReadAdView)
            webviewHelperSynch.updateSlot(adRatio.getAdSlotRatio(webview.measuredWidth))
        }

        override fun onAdRatioUpdate(adRatio: AdRatio) {
            // Will update the ratio with the new ratio received from ad experience
            webviewHelperSynch.updateSlot(adRatio.getAdSlotRatio(webview.measuredWidth))
        }

        override fun onAdClosed() {
            webviewHelperSynch.closeAd()
        }
        override fun onAdError(code: Int, description: String) {
            webviewHelperSynch.clean()
        }
        override fun onFailToReceiveAd(failReason: String) {
            webviewHelperSynch.clean()
        }
        override fun onAdClicked() {}
            override fun onAdImpression() {}
        })
}

Event Monitoring

The Teads inApp SDK provides a set of listeners to let you monitor a large scope of events all along ad life cycle. This helps tailor the ad experience in your app, e.g., closing the ad view in case of onAdError, resize the ad view in case of onAdRatioUpdate.

interface InReadAdListener {
    // When an impression has occurred
    fun onAdImpression()
    // When an event click has been fired
    fun onAdClicked()
    // When the ad experience has experienced an issue
    fun onAdError(code: Int, description: String)
    // When the ad has been closed
    fun onAdClosed()
    // This is the entry point of an Ad correctly loaded by Teads
    fun onAdReceived(inReadAdView: InReadAdView, adRatio: AdRatio)
    // When Teads inApp SDK has failed to retrieve an ad
    fun onFailToReceiveAd(failReason: String)
    // This is the monitoring slot tracker view (see Slot Monitoring section below)
    fun adOpportunityTrackerView(trackerView: AdOpportunityTrackerView)
    // When an ad has updated its ratio, you need to update your container view
    fun onAdRatioUpdate(adRatio: AdRatio)
}

Configuration Changes

Some applications handle the configuration change themselves instead of letting the Android system restarting their activity. This is particularly the case for screen rotation and screen size configuration.

If you have declared in your manifest that you handle the configuration change by adding the android:configChanges attribute, then you must notify the event to the Webview Helper. It will be responsible to calculate the new size and the new coordinates of the ad slot.

override fun onConfigurationChanged(newConfig: Configuration) {
    super.onConfigurationChanged(newConfig)
    webviewHelperSynch.onConfigurationChanged()
}

Brand Safety and web content URL

Having brand safe content will optimize fill rate since advertisers are less keen to have their brand associated with "bad" context (violence/adult etc.).

⚠️ Teads guarantees brand safe contents to advertiser by analysing the overall content of the loaded page. This is an important requirement for advertiser. The Fill Rate of your app could be impacted if BrandSafety analysis is not enabled.

The categorization is done on the fly by a 3rd party partner, Grapeshot.

Brand safe analyze is limited to web content only.
This technical limitation is bypassed inApp using pageSlotUrl to provide the Web equivalent URL of the current article Grapeshot will perform analysis in.

If your application doesn't have a website equivalent, the pageSlotUrl method can be ignored.

AdSettings.Builder()
.pageSlotUrl("https://example.com/my_article_1")
.build()

Check list

  • ✅ Ensure Brand Safety is enabled
  • ✅ Ensure you comply with privacy legal requirements (GDPR/CCPA/GPP)
  • ✅ Comply with app-ads.txt
  • ✅ Enable ad view resizing
  • ✅ Enable slot monitoring for ad opportunities
  • ✅ Clean the ad view when necessary
  • ✅ Test different PIDs with various ad formats and sizes
  • ✅ Enable validation mode to ensure key features are working

Additional settings

Find the full available AdPlacementSettings and AdRequestSettings settings here:

Example:

AdPlacementSettings.Builder()
// Enable debug logs
.enableDebug()
// GDPR
.userConsent([SUBJECT_TO_GDPR], [CONSENT_STRING], TCFVersion.V2, cmpSdkId)
.build()

Did you find it helpful? Yes No

Send feedback
Sorry we couldn't be helpful. Help us improve this article with your feedback.