# Tapsell Developers — Full Documentation > Generated from https://developer.tapsell.ir. 170 pages. --- # Getting Started Source: https://developer.tapsell.ir/docs Section: Documentation Tapsell provides you a SDK so that you can easily use Tapsell with any type of application you have, easily implement the Tapsell SDK in your application and earn money from ads. Tapsell's publisher relations team is also with you from the very beginning of the Tapsell SDK implementation to help you achieve the maximum advertising capacity without harming the user experience and get the most profit from ads by optimally implementing the SDK. :::success Documentations - [Publishers docs](publishers) - [Advertisers docs](advertisers) ::: --- # FAQ Source: https://developer.tapsell.ir/docs/advertisers/faq Section: Documentation # FAQ --- # Getting Started Source: https://developer.tapsell.ir/docs/advertisers/intro Section: Documentation # Getting Started --- # Playable ads Source: https://developer.tapsell.ir/docs/advertisers/playable Section: Documentation Playable ads are interactive ads that allow users to interact with—or play with—the core functionality of an app or game, like a free demo. Users get to experience an app, product, or game before they commit to downloading or purchasing it. ### Upload Playable Script First, you need to create an `index.html` file in your project according to the structure below. Then, **[download](https://cdn.tapture.ir/tapsell/app/frontend/playable/tapsell-playable.js) `tapsell-playable.js` script** and add it to your project. Finally, enter its path in the script tag as shown below to ensure optimal access to Tapsell functions. ```html ``` According to the code above, the `start`, `pause`, and `resume` functions are called by the Tapsell SDK, and you can implement the relevant content in each of them: - **`start`**: This function is called when the content of your desired ad is ready to be displayed. Therefore, you need to begin displaying your content in this function. - **`pause`**: This function is called when the content of your desired ad has been paused. In this function, you should deactivate any audio content that is currently playing. - **`resume`**: This function is called when the content of your desired ad is resumed. Failure to implement any of the above functions may result in the ad not being displayed or experiencing disruptions. ### Show Ad To show ad, you need to call the following function: ```js window.PLAYABLE.isReady() ``` By calling this function, the Tapsell SDK will invoke the `start` function you have implemented above, and your ad will be displayed. Therefore, failing to call this function will result in the ad not being displayed. ### Click To click on ad, you need to call the following function: ```js window.PLAYABLE.click(); ``` ### Destroy Ad When the user clicks on the close button of the banner, this function needs to be called. ```js window.PLAYABLE.close() ``` ### Publish After implementation, you need to send your project to us in the form of a `zip` file. --- # FAQ Source: https://developer.tapsell.ir/docs/advertisers/retargeting/faq Section: Documentation ## General Questions **Q1: What is the Retargeting Script?** A: The Retargeting Script is a JavaScript library that helps you track user interactions on your website, such as clicks and form submissions, and trigger retargeting tags for advertising purposes. **Q2: How do I install the script?** A: Add the script script to your website and configure tag IDs with CSS selectors for the elements you want to track. See the [Installation Guide](#installation) for details. **Q3: Is the script compatible with all browsers?** A: The script works on all modern browsers that support standard JavaScript, including Chrome, Firefox, Edge, and Safari. --- ## Tag and Tracking **Q4: What is a tag ID?** A: A tag ID is a unique identifier for a specific action or conversion you want to track. It tells the script which retargeting tag to fire when the user interacts with a defined element. **Q5: How do I find the CSS selector for an element?** A: Inspect your page using developer tools (right-click → Inspect) and find the class or ID of the element. Use `.classname` for classes and `#idname` for IDs in your `css_selector`. **Q6: Can I track multiple elements on the same page?** A: Yes. Simply add multiple objects in the `window.retargetingTags` array with different tag IDs and CSS selectors. --- ## Troubleshooting **Q7: The script isn’t firing. What should I check?** A: - Make sure the script is included **before the closing `` tag**. - Verify that `{adviserId}` is correctly replaced with your adviser ID. - Ensure the CSS selector matches an element on your page. **Q8: Tags are not triggering on clicks.** A: - Check that the element exists when the page loads. - For dynamically loaded elements (e.g., via AJAX), use a MutationObserver to ensure the script can detect them. **Q9: Can I use the script with a single-page application (SPA)?** A: Yes, but you may need to manually reinitialize the script or trigger tag checks after page route changes. --- # Installation Source: https://developer.tapsell.ir/docs/advertisers/retargeting/installation Section: Documentation To install the Retargeting Script on your website, follow these steps: ## 1. Add the script Paste the following snippet **before the closing `` tag** on your pages: ```html ``` ## 2. Adding tag id and css selectors into page Paste the following snippet **before the closing `` tag** on your pages: ```html ``` --- # Quickstart Source: https://developer.tapsell.ir/docs/advertisers/retargeting/quickstart Section: Documentation Start tracking visitors in **under a minute** — no setup required. Just **paste this script** on your page (replace `{adviserId}` with your ID): ```html ``` --- # FAQ Source: https://developer.tapsell.ir/docs/faq Section: Documentation If you are an ad publisher or advertiser, you can view frequently asked questions related to each in this section. :::info help section - [Publishers](faq) - [Advertisers](advertisers/faq) ::: --- # Support Source: https://developer.tapsell.ir/docs/support Section: Documentation You can choose one of the following ways to proceed your issues: :::info Support ways - Check Frequently Asked Question on [FAQ](faq) links - Check reported issues on [GitHub](https://github.com/tapsellorg/TapsellMediation-AndroidSample/issues) - Use our **[AI ChatBot](support)** to fix your all implementation or general issues in 24 hours a day - Create ticket in your [console](https://app.tapsell.ir) - If none of the above ways work, you can also ask your question from [Telegram Tapsell Technical support](https://t.me/TapsellTechSupport) ID ::: --- # Introduction Source: https://developer.tapsell.ir/docs/sdk Section: Mobile SDK Tapsell provides you a SDK so that you can easily use Tapsell with any type of application you have, easily implement the Tapsell SDK in your application and earn money from ads. Tapsell's publisher relations team is also with you from the very beginning of the Tapsell SDK implementation to help you achieve the maximum advertising capacity without harming the user experience and get the most profit from ads by optimally implementing the SDK. ## Mediation SDK {#mediation} :::success ‌ Tapsell Mediation, is a Mediated solution helping businesses increase their mobile apps’ revenue with the inclusion of other supported Programmatic & Mediated Ad Solutions. Integrating the Tapsell SDK into your app is the first step toward displaying ads and earning revenue. Once you’ve integrated the SDK, you can choose an ad format (such as native or rewarded video) and follow the steps to implement it. - [Android Studio docs](./platforms/android) - [Unity docs](./platforms/unity) - [Flutter docs](./platforms/flutter) - [React Native docs](./platforms/reactnative) ::: ## Tapsell Plus SDK :::warning This library will not be supported in the future If you have been using Tapsell Plus for in-app advertising so far, it is better to use the [Tapsell Mediation SDK](#mediation) as a replacement. The Tapsell Mediation SDK, in addition to having all the features of Tapsell Plus, provides smarter algorithms, more diverse ads, and better performance. Released versions of Tapsell Plus will continue to work and receive ads if they have already been implemented; however, they will not be updated and bugs will not be supported. - [Android docs](/docs/sdk-legacy-tapsell-plus/android) - [Unity docs](/docs/sdk-legacy-tapsell-plus/unity) - [Flutter docs](/docs/sdk-legacy-tapsell-plus/flutter) - [React Native docs](/docs/sdk-legacy-tapsell-plus/reactnative) - [B4A docs](/docs/sdk-legacy-tapsell-plus/b4a) ::: ## Tapsell SDK :::danger This library is no longer supported If you have been using Tapsell for in-app advertising so far, it is better to use the [Tapsell Mediation SDK](#mediation) as a replacement. The Tapsell Mediation SDK, in addition to having all the features of Tapsell, provides smarter algorithms, more diverse ads, and better performance. It also provides the opportunity to earn foreign-currency revenue by showing ads from external ad networks (such as Google AdMob). - [Android docs](/docs/sdk-legacy/android) - [Unity docs](/docs/sdk-legacy/unity) - [React Native docs](/docs/sdk-legacy/reactnative) - [B4A docs](/docs/sdk-legacy/b4a) ::: --- # Changelog Source: https://developer.tapsell.ir/docs/sdk/changelog Section: Mobile SDK ## Version 1.4 {#1.4} ### 1.4.0-alpha03 {#1.4.0-alpha03} Published in 2026-08-08 #### Common {#1.4.0-alpha03-common} - Added `ir.tapsell.mediation.AUTO_INIT` manifest flag to opt out of automatic ContentProvider-based SDK initialization. When set to `false`, publishers must call `Tapsell.initialize(Context)` manually from `Application.onCreate()`. This feature is only available on the Android-native flavor (not Flutter, React Native, or Unity). - Supported `secret-key` as an alternative to UUID-based `app-id` in the `AndroidManifest` meta-data. - Upgraded `Legacy` adapter to `4.9.16`: - Fixed `NetworkOnMainThread` exception when closing rewarded ads. - `Legacy-Taproll` improvements: - Redesigned overlay API: replaced fixed-view `AdOverlay` with lifecycle-based interface, added `AdInfo` data class, and `ViewOverlayAdapter` for default look. - Fixed midroll pod index mapping and stale ad overlay on backward seek. - Fixed rewarded ad completion state being reported incorrectly when the ad is closed. #### Unity {#1.4.0-alpha03-unity} - No platform-specific changes. #### React Native {#1.4.0-alpha03-reactnative} - Fixed namespace collision with the native mediation SDK. - Fixed tapsell imports to resolve from source instead of the built lib. - Updated the project to align with the React Native `0.77` templates. #### Flutter {#1.4.0-alpha03-flutter} - Removed unused dependencies from some packages, including `analyzer` and `plugin_platform_interface`. This fixes the `analyzer` version conflict with packages such as `freezed` 3.x, as reported in [20](https://github.com/tapsellorg/Discussion/discussions/20). ### 1.4.0-alpha02 {#1.4.0-alpha02} Published in 2026-06-08 #### Common {#1.4.0-alpha02-common} - Added **Taproll (Tapsell's in-stream ads SDK)** support as an alternative for Google IMA for serving preroll video ads. More info. - Log installed and active ad networks on SDK startup to aid debugging during development. - Improve time synchronization reliability when internet access is restricted. - Fix a brief visual flash when closing rewarded video ads. #### Unity {#1.4.0-alpha02-unity} - Fixed an issue where native ads failed to show; The managed code linker was stripping auto-initialization from the `Admob` and `Legacy` adapters. - Improved rendering of portrait images in native ads of the `Legacy` adapter. - Sample project upgrade and improvements: - Improved RTL sample of Native Ad scenes. - Migrated **EDM4U** from bundled `1.2.186` DLLs to UPM package (`com.google.external-dependency-manager`). - Upgraded **TextMesh Pro** (TMP) package. - Migrated **RTLTMPro** from bundled assets to UPM package (`com.nosuchstudio.rtltmpro`), removed old source files. - Added in-game debug console (`com.yasirkula.ingamedebugconsole`) to sample scenes for runtime log inspection. - Added **Android Logcat** (`com.unity.mobile.android-logcat`) for viewing device logs in Unity Editor. - Upgraded other Unity packages (collab-proxy, IDE tools, uGUI to latest version). #### React Native {#1.4.0-alpha02-reactnative} - No release #### Flutter {#1.4.0-alpha02-flutter} - No release ### 1.4.0-alpha01 {#1.4.0-alpha01} Published in 2026-03-13 #### Common {#1.4.0-alpha01-common} - Support [16KB page size](https://developer.android.com/guide/practices/page-sizes) for native libs to Android 15+ compatibility on 64-bit devices. - A lot of optimizations has applied on core functionalities. #### Unity {#1.4.0-alpha01-unity} **Unity Editor:** - New Adapter management in the **Tapsell Settings Window** (`Assets > Tapsell Mediation > Settings`): - Enable or disable each ad network adapter (Legacy, Admob, Applovin, Chartboost, Fyber, IronSource, Liftoff, Mintegral, UnityAds, Wortise, Yandex) without manually editing XML files. - Zone type support table per adapter (Rewarded, Interstitial, Banner, Native, PreRoll). - Driver installation status for adapters that require a separate driver package (`Admob`, `Legacy`), with a direct install link. - `TapsellMediationDependencies.xml` is now dynamically regenerated based on enabled adapters, so only selected networks are resolved by EDM4U. - SDK modules are now distributed as pre-compiled DLLs instead of C# source files. - Tapsell keys are now stored in `ProjectSettings/TapsellMediationSettings.json` to simplify upgrading the package without losing configurations. - [Breaking - Action required]: Re-enter keys in the **Tapsell Settings Window** - Traditional `` tags in custom `AndroidManifest.xml` have been removed. Keys are now provided via `manifestPlaceholders` in `Assets/Plugins/Android/launcherTemplate.gradle`. This is done automatically, but `Assets -> Tapsell Mediation -> Force Refresh Keys` is available too. - [Breaking - Action required]: Enable **Custom Launcher Gradle Template** in **Player Settings** if it is not already enabled. - **Custom Main Manifest** is no longer required by **Tapsell Mediation SDK**. - Introduced `maven.tapsell.ir` repo in packages. - Add fast access items in `Assets > Tapsell Mediation` to documentations and changelogs. - Provide package version via `Tapsell` class, also show it in Tapsell setting window **SDK:** - Optimize loading images in native-ads of `Legacy` adapter. #### React Native {#1.4.0-alpha01-reactnative} - No release #### Flutter {#1.4.0-alpha01-flutter} - No release ## Version 1.3 {#1.3} ### 1.3.0 {#1.3.0} Published in 2026-04-20 This release is identical to [1.3.0-beta06](#1.3.0-beta06). Below is the full list of changes since [1.2.0](#1.2.0): #### Common {#1.3.0-common} - Upgraded Tapsell Legacy adapter to [4.9.15](/docs/sdk-legacy/platforms/android/changelog#4.9.15). - Prevented screen from turning off during video ad playback. - Fixed a rare rewarded-ad crash on unstable network connections. - Added Android 15 [edge-to-edge](https://developer.android.com/develop/ui/views/layout/edge-to-edge) compatibility. - Improved R8 fullMode compatibility. - Bump `compile-sdk` version into `35`. - Improved reliability in network restrictions. - Reduced adapter dependency conflicts in `admob`, `applovin`, `chartboost`, `ironsource`, `wortise`, `yandex` adapters. - Migrated `ironsource` to new dependency `com.unity3d.ads-mediation:mediation-sdk` to be resolvable from `MavenCentral`. - Reduced the size of SDK. - Minor internal improvements. #### Unity {#1.3.0-unity} - Refactored `gradle.properties` processor to improve reliability and handle file modifications more safely. - Improved error handling in native-ads. - Introduced `maven.tapsell.ir` repo in packages [backport from #1.4.0-alpha01] #### React Native {#1.3.0-reactnative} - No release #### Flutter {#1.3.0-flutter} - Renamed `tapsell_legacy_adapter` into `tapsell_mediation_legacy` for native ads using `legacy` adapter. - Introduced `maven.tapsell.ir` repo in packages [backport from #1.4.0-alpha01] - Update `google_mobile_ads` dependency to version `5.2.0` in the `admob` adapter package. - Upgrade Android development toolchain including Gradle, Kotlin, and Mockito to their latest stable versions. - Migrate all Android build scripts from Groovy to Kotlin DSL and consolidate them into a unified configuration structure. ### 1.3.0-beta06 {#1.3.0-beta06} Published in 2026-02-10 #### Common {#1.3.0-beta06-common} - Upgraded Tapsell Legacy adapter to [4.9.15](/docs/sdk-legacy/platforms/android/changelog#4.9.15). - Prevented screen from turning off during video ad playback. - Fixed a rare rewarded-ad crash on unstable network connections - Added Android 15 [edge-to-edge](https://developer.android.com/develop/ui/views/layout/edge-to-edge) compatibility #### Unity {#1.3.0-beta06-unity} - No platform-specific changes. #### React Native {#1.3.0-beta06-reactnative} - Introduced `maven.tapsell.ir` repo in packages [backport from #1.4.0-alpha01] #### Flutter {#1.3.0-beta06-flutter} - Introduced `maven.tapsell.ir` repo in packages. [backport from #1.4.0-alpha01] - Update `google_mobile_ads` dependency to version `5.2.0` in the `admob` adapter package. - Upgrade Android development toolchain including Gradle, Kotlin, and Mockito to their latest stable versions. - Migrate all Android build scripts from Groovy to Kotlin DSL and consolidate them into a unified configuration structure. ### 1.3.0-beta05 {#1.3.0-beta05} Published in 2026-02-07 #### Common {#1.3.0-beta05-common} - Optimize reliability mechanisms in network restrictions. #### Unity {#1.3.0-beta05-unity} - No platform-specific changes. #### React Native {#1.3.0-beta05-reactnative} - No release #### Flutter {#1.3.0-beta05-flutter} - No release ### 1.3.0-beta04 {#1.3.0-beta04} Published in 2026-01-31 #### Common {#1.3.0-beta04-common} - Improved reliability in network restrictions. #### Unity {#1.3.0-beta04-unity} - No platform-specific changes. #### React Native {#1.3.0-beta04-reactnative} - No release #### Flutter {#1.3.0-beta04-flutter} - No release ### 1.3.0-beta03 {#1.3.0-beta03} Published in 2026-01-28 #### Common {#1.3.0-beta03-common} - Bump `compile-sdk` version into `35`. - Prevent the screen from turning off during video ad playback. - Minor internal improvements. #### Unity {#1.3.0-beta03-unity} - Refactor `gradle.properties` processor to improve reliability and handle file modifications more safely. - Improve error handling in native-ads. #### React Native {#1.3.0-beta03-reactnative} - No release #### Flutter {#1.3.0-beta03-flutter} - No release ### 1.3.0-beta02 {#1.3.0-beta02} Published in 2025-11-17 #### Common {#1.3.0-beta02-common} - Upgraded Tapsell Legacy adapter to [4.9.14](/docs/sdk-legacy/platforms/android/changelog#4.9.14). - Improved R8 fullMode compatibility. - Reduce adapters dependency to remove its dependency conflict in some edge-cases in `admob`, `applovin`, `chartboost`, `ironsource` , `wortise`, `yandex` adapters. - Migrate `ironsource` to new dependency `com.unity3d.ads-mediation:mediation-sdk` to be resolvable from `MavenCentral`. - Minor internal improvements. #### Unity {#1.3.0-beta02-unity} - No platform-specific changes. #### React Native {#1.3.0-beta02-reactnative} - No platform-specific changes. #### Flutter {#1.3.0-beta02-flutter} - Renamed `tapsell_legacy_adapter` into `tapsell_mediation_legacy` for native ads using `legacy` adapter. ### 1.3.0-beta01 {#1.3.0-beta01} Published in 2025-10-21 #### Common {#1.3.0-beta01-common} - Reduce the size of SDK. - Minor internal improvements. #### Unity {#1.3.0-beta01-unity} - No release #### React Native {#1.3.0-beta01-reactnative} - No release #### Flutter {#1.3.0-beta01-flutter} - No release ## Version 1.2 {#1.2} ### 1.2.0 {#1.2.0} Published in 2025-10-08 #### Common {#1.2.0-common} - Added support for [edge-to-edge](https://developer.android.com/develop/ui/views/layout/edge-to-edge) layouts to ensure Android `15` compatibility. - Enhanced image loading functionality by integrating with host-app image loaders (`Coil` and `Glide` currently supported). - Optimized proguard rules for improved R8 fullMode compatibility. - Various performance improvements and bug fixes. #### Unity {#1.2.0-unity} - Updated Unity editor compatibility to `2021.3.45f2`. - Upgraded **EDM4U** dependency to `1.2.186`. - Updated Android **target-sdk** to API level `34`. - Raised Android **min-sdk-version** to API level `24` to resolve Kotlin dexing issues on older versions [source](https://stackoverflow.com/a/78401220/2389923). - Included Unity `*.meta` files in project structure. - Added Appodeal maven repository support for `Chartboost` adapter integration. - Removed version prefix (`v`) from package naming convention. #### React Native {#1.2.0-reactnative} - No release #### Flutter {#1.2.0-flutter} - No release ## Version 1.1 {#1.1} ### 1.1.0 {#1.1.0} Published in 2025-09-14 #### Common {#1.1.0-common} - Upgraded Tapsell Legacy adapter to [4.9.13](/docs/sdk-legacy/platforms/android/changelog#4.9.13). - Fixed ANR issue in video ads by migrating Android Media Player to `ExoPlayer`. - Upgraded OkHttp to [4.11.0](https://square.github.io/okhttp/changelogs/changelog_4x/#version-4110). - Enhanced video player performance for smoother ad playback. - Optimized network data usage efficiency to reduce bandwidth consumption. - Improved image-downloader and resource management for better memory usage. - Improved **CafeBazaar**'s modal launching for a more seamless experience. - Suppressed **GooglePlayService** outdated notification to avoid distracting users. - Fixed the issue of **IntentChooser** dialog appearing twice. - Resolved an issue with back button press handling. - Utilized the `tpsl` prefix for the obfuscation dictionary to position our classes at the bottom of IDE suggestions & improving code navigation. - Additional internal optimizations and improvements. #### Unity {#1.1.0-unity} - Move `TapsellMediationAdmobAdapterSignature` to admob plugin #### React Native {#1.1.0-reactnative} - No release #### Flutter {#1.1.0-flutter} - Move `TapsellMediationAdmobAdapterSignature` to admob plugin. ## Version 1.0 {#1.0} ### 1.0.2-beta09 {#1.0.2-beta09} Published in 2025-05-15 #### Common {#1.0.2-beta09-common} - Upgraded Tapsell Legacy adapter to [4.9.11](/docs/sdk-legacy/platforms/android/changelog#4.9.11) - Fixed showing close icon in the interstitial banner when rotation happens. - Reduce conflict between multiple adapters like `chartboost`, `mintegral`, `pangle` and `google-ads`. - Additional internal optimizations and improvements. #### Unity #02 {#1.0.2-beta09-unity-02} - Fixed startup crash `NoSuchMethodError` by adding missed runtime dependencies: `androidx.core:core-ktx` and `androidx.lifecycle:lifecycle-process`. The exact error log message: ``` Error JavaBinder *** Uncaught remote exception! (Exceptions are not yet supported across processes.) Error JavaBinder java.lang.NoSuchMethodError: No static method registerReceiver(Landroid/content/Context;Landroid/content/BroadcastReceiver;Landroid/content/IntentFilter;Ljava/lang/String;Landroid/os/Handler;I)Landroid/content/Intent; in class Landroidx/core/content/ContextCompat; or its super classes (declaration of 'androidx.core.content.ContextCompat' appears in /data/app/packagename-8jC3eOK_gulNllIYqZiLiQ==/base.apk) ``` #### Unity #01 {#1.0.2-beta09-unity-01} - Fixed the duplicated keys existence in `gradleTemplate.properties` #### React Native {#1.0.2-beta09-reactnative} - No release #### Flutter {#1.0.2-beta09-flutter} - No release ### 1.0.2-beta08 {#1.0.2-beta08} Published in 2025-05-15 #### Common {#1.0.2-beta08-common} - Added an error message for onFailure callback in RequestResultListener. - Upgraded Tapsell Legacy adapter version to v4.9.10 - Fix the back navigation issue to avoid side effects on global back navigation. #### Unity {#1.0.2-beta08-unity} - Add `message` field for `onFailure` callback in requests. #### React Native {#1.0.2-beta08-reactnative} - Add `message` field for `onFailure` callback in requests. #### Flutter {#1.0.2-beta08-flutter} - Add `message` field for `onFailure` callback in requests. ### 1.0.2-beta07 {#1.0.2-beta07} Published in 2025-04-22 #### Common {#1.0.2-beta07-common} - Downgraded Applovin Admob adapter version to v23.4.0.0 to fix compile issues in Unity 2021 #### Unity {#1.0.2-beta07-unity} - No release #### React Native {#1.0.2-beta07-reactnative} - No release #### Flutter {#1.0.2-beta07-flutter} - No release ### 1.0.2-beta06 {#1.0.2-beta06} Published in 2025-03-10 #### Common {#1.0.2-beta06-common} - Upgraded Tapsell Legacy adapter version to v4.9.9 to support new back navigation API in Android 13+ - Downgraded Admob version to v23.4.0 to fix compile issues in Unity 2021 #### Unity {#1.0.2-beta06-unity} - No release #### React Native {#1.0.2-beta06-reactnative} - No release #### Flutter {#1.0.2-beta06-flutter} - No release ### 1.0.2-beta05 {#1.0.2-beta05} Published in 2025-03-10 #### Common {#1.0.2-beta05-common} - Upgraded Tapsell Legacy adapter version to v4.9.8: Fixed conflict with InAppBilling SDKs. - Upgraded Admob version to v23.6.0 - Upgraded Yandex version to v7.6.0.0. - Upgraded Applovin version to v13.1.0. - Upgraded IronSource version to v8.6.1. - Upgraded Mintegral version to v16.8.61. - Upgraded Vungle version to v7.4.3. - Upgraded UnityAds version to v4.13.1. - Upgraded Fyber (Digital Turbine Exchange) version to v8.3.6. - Upgraded Wortise version to v1.6.1. #### Unity {#1.0.2-beta05-unity} - No release #### React Native {#1.0.2-beta05-reactnative} - No release #### Flutter {#1.0.2-beta05-flutter} - No release ### 1.0.2-beta04 {#1.0.2-beta04} Published in 2025-01-26 #### Common {#1.0.2-beta04-common} - Changed validation of zone id and app key format. - Improved functionality of the SDK #### Unity {#1.0.2-beta04-unity} - No release #### React Native {#1.0.2-beta04-reactnative} - Remove `Flipper` from project. It is integrated by ReactNative automatically #### Flutter {#1.0.2-beta04-flutter} - No release ### 1.0.2-beta03 {#1.0.2-beta03} Published in 2024-12-23 #### Common {#1.0.2-beta03-common} - Added onAdClosed callback for native ads to identify video completion state. - Upgraded Tapsell Legacy adapter version to v4.9.7-rc01. Migrated from Android MediaPlayer to ExoPlayer #### Unity {#1.0.2-beta03-unity} - No release #### React Native {#1.0.2-beta03-reactnative} - No release #### Flutter {#1.0.2-beta03-flutter} - No release ### 1.0.2-beta02 {#1.0.2-beta02} Published in 2024-11-13 #### Common {#1.0.2-beta02-common} - Added support for fully clickable native videos - Upgraded Tapsell Legacy adapter version to v4.9.4 #### Unity {#1.0.2-beta02-unity} - No release #### React Native {#1.0.2-beta02-reactnative} - No release #### Flutter {#1.0.2-beta02-flutter} - No release ### 1.0.2-beta01 {#1.0.2-beta01} Published in 2024-11-05 #### Common {#1.0.2-beta01-common} - Added support to play native videos automatically #### Unity {#1.0.2-beta01-unity} - No release #### React Native {#1.0.2-beta01-reactnative} - No release #### Flutter {#1.0.2-beta01-flutter} - Added Native Banner support ### 1.0.1-beta09 {#1.0.1-beta09} Published in 2024-10-20 #### Common {#1.0.1-beta09-common} - Fixed issue in playing native video ad #### Unity {#1.0.1-beta09-unity} - No release #### React Native {#1.0.1-beta09-reactnative} - No release #### Flutter {#1.0.1-beta09-flutter} - No release ### 1.0.1-beta08 {#1.0.1-beta08} Published in 2024-09-30 #### Common {#1.0.1-beta08-common} - Added Yandex mediation AdNetwork adapter - Removed developer market from user consent management - Upgraded targetSdk to version 34 (Android 14) - Upgraded Admob version to v23.0.0 - Upgraded Applovin adapter to v12.6.0: No need to use applovin sdk key in AndroidManifest.xml. - Upgraded Tapsell Legacy adapter version to v4.9.3 - Upgraded IronSource adapter version to v8.2.1 - Upgraded UnityAds adapter version to v4.12.2 - Upgraded Mintegral adapter version to v16.8.11 - Upgraded Fyber (Digital Turbine Exchange) adapter version to v8.3.0 - Upgraded Chartboost adapter version to v4.9.1 #### Unity {#1.0.1-beta08-unity} - No release #### React Native {#1.0.1-beta08-reactnative} - No release #### Flutter {#1.0.1-beta08-flutter} - Added destroy banner method ### 1.0.1-beta07 {#1.0.1-beta07} Published in 2024-09-30 #### Common {#1.0.1-beta07-common} - Improve GDPR user consent flow for GooglePlay users #### Unity {#1.0.1-beta07-unity} - Added RTL unity package #### React Native {#1.0.1-beta07-reactnative} - No release #### Flutter {#1.0.1-beta07-flutter} - No release ### 1.0.1-beta06 {#1.0.1-beta06} Published in 2024-04-30 #### Common {#1.0.1-beta06-common} - Added AppOpen ad type. This type is currently supported by Admob, Applovin and Wortise. - Added Adaptive banner size for all external ad networks. - Changed user consent approach in Admob adapter. load and show consent form only when required. - Upgraded Tapsell Legacy adapter version to v4.9.0 - Upgraded Mintegral version to v16.6.71 - Upgraded Wortise adapter version to v1.5.1. Adding pangle maven url is required now. #### Unity {#1.0.1-beta06-unity} - Added support for Unity 2020 #### React Native {#1.0.1-beta06-reactnative} - Initialized plugin #### Flutter {#1.0.1-beta06-flutter} - Initialized plugin ### 1.0.1-beta05 {#1.0.1-beta05} Published in 2024-03-02 #### Common {#1.0.1-beta05-common} - Fixed PreRoll Media3 crash on Android 6 - Added few Proguard rules - Upgraded Tapsell Legacy adapter version to v4.9.3. Some proguard rules were updated - Upgraded Admob version to v22.6.0 - Upgraded Mintegral version to v16.6.34 - Upgraded IronSource version to v7.8.0 - Upgraded Applovin version to v12.2.0 - Upgraded Chartboost version to v4.8.0 - Upgraded UnityAds version to v4.9.2 #### Unity {#1.0.1-beta05-unity} - No release #### React Native {#1.0.1-beta05-reactnative} - No release #### Flutter {#1.0.1-beta05-flutter} - No release ### 1.0.1-beta04 {#1.0.1-beta04} Published in 2024-01-10 #### Common {#1.0.1-beta04-common} - Improvements on Tapsell.requestMultipleNativeAds() to fix error previous request is still trying ... #### Unity {#1.0.1-beta04-unity} - No release #### React Native {#1.0.1-beta04-reactnative} - No release #### Flutter {#1.0.1-beta04-flutter} - No release ### 1.0.1-beta03 {#1.0.1-beta03} Published in 2023-12-19 #### Common {#1.0.1-beta03-common} - Added support for fully clickable native ads #### Unity {#1.0.1-beta03-unity} - No release #### React Native {#1.0.1-beta03-reactnative} - No release #### Flutter {#1.0.1-beta03-flutter} - No release ### 1.0.1-beta02 {#1.0.1-beta02} Published in 2024-12-11 #### Common {#1.0.1-beta02-common} - No major Changes #### Unity {#1.0.1-beta02-unity} - No release #### React Native {#1.0.1-beta02-reactnative} - No release #### Flutter {#1.0.1-beta02-flutter} - No release ### 1.0.1-beta01 {#1.0.1-beta01} Published in 2023-12-11 #### Common {#1.0.1-beta01-common} - Added pause and resume feature to Native video according to the app lifecycle state. this pauses the video in onPause and resume it in onResume - Fixed showing default video in pre-roll ad. - Fixed PreRoll UI issues. #### Unity {#1.0.1-beta01-unity} - No release #### React Native {#1.0.1-beta01-reactnative} - No release #### Flutter {#1.0.1-beta01-flutter} - No release ### 1.0.0-beta10 {#1.0.0-beta10} Published in 2023-10-17 #### Common {#1.0.0-beta10-common} - Added PreRoll IMA to Mediation with Media3 ExoPlayer. - Added few GDPR changes. Added developer market key - Added Gradle 8 proguard R8 rules for Tapsell legacy adapter, Retrofit, OkHttp, IMA and ExoPlayer - Upgraded Tapsell Legacy adapter version to v4.8.5 #### Unity {#1.0.0-beta10-unity} - No release #### React Native {#1.0.0-beta10-reactnative} - No release #### Flutter {#1.0.0-beta10-flutter} - No release ### 1.0.0-beta09 {#1.0.0-beta09} Published in 2023-09-19 #### Common {#1.0.0-beta09-common} - Added optional custom parameters for all requests to pas extra info: @Nullable Map requestParams #### Unity {#1.0.0-beta09-unity} - No release #### React Native {#1.0.0-beta09-reactnative} - No release #### Flutter {#1.0.0-beta09-flutter} - No release ### 1.0.0-beta08 {#1.0.0-beta08} Published in 2023-09-03 #### Common {#1.0.0-beta08-common} - Added User consent configs for GDPR in Tapsell and all other AdNetwork adapters - Changed the ad networks initialization state listener. Initialize SDK when at least one of the ad networks is initialized successfully. - Added IronSource AdNetwork adapter. - Added Vungle(Liftoff) AdNetwork adapter. #### Unity {#1.0.0-beta08-unity} - No release #### React Native {#1.0.0-beta08-reactnative} - No release #### Flutter {#1.0.0-beta08-flutter} - No release ### 1.0.0-beta07 {#1.0.0-beta07} Published in 2023-08-14 #### Common {#1.0.0-beta07-common} - Upgraded Tapsell Legacy adapter version to v4.9.4. Removed Collecting user's installed apps due to Google Play policy error. #### Unity {#1.0.0-beta07-unity} - No release #### React Native {#1.0.0-beta07-reactnative} - No release #### Flutter {#1.0.0-beta07-flutter} - No release --- # Compatibility Matrix Table Source: https://developer.tapsell.ir/docs/sdk/compatibility-matrix Section: Mobile SDK The tables below shows the versions mapping between Mediation SDK and Tapsell internal plugin versions. ## Internal Plugins | Tapsell Mediation Version | Gradle Version | Kotlin Version | |:-------------------------:|:--------------:|:--------------:| | `1.1.0` | `7.6.1` | `1.8.20` | ## Internal Ad Networks | Tapsell Mediation Version | Tapsell Legacy Version | Admob Version | |:-------------------------:|:----------------------:|:-------------:| | `1.1.0` | `4.9.10` | `22.6.0` | --- # FAQ Source: https://developer.tapsell.ir/docs/sdk/faq Section: Mobile SDK ## Common/Android ##### Error `D8: java.lang.NullPointerException: Cannot invoke "String.length()" because "" is null` [^](https://github.com/koral--/android-gif-drawable/issues/869) {#r8-upgrade} This issue will be occurred when you're using `AGP < 8`. To fix this issue in building, the `R8` dependency must be upgraded by: ```groovy // Project-level build.gradle.kts file buildscript { dependencies { // ... classpath("com.android.tools:r8:8.1.56") } } ``` ```groovy // Project-level build.gradle file buildscript { dependencies { // ... classpath 'com.android.tools:r8:8.1.56' } } ``` --- # Banner Ads Source: https://developer.tapsell.ir/docs/sdk/platforms/android/ad-formats/banner Section: Mobile SDK Banner ads are rectangular ads that appear on the device screen usually at the top or bottom. Banner ads stay on screen while users are interacting with the app, and can refresh automatically after a certain period of time. If you’re new to mobile advertising, they’re a great place to start. This guide shows you how to integrate banner ads from Tapsell into your Android app. ## Prerequisite 1. Follow the SDK integration steps described in [Quick start](../quick-start). 2. Make sure you're running the latest Tapsell Mobile Ads SDK version. :::info latest SDK version [![Maven Central](https://img.shields.io/maven-central/v/ir.tapsell/tapsell)](https://search.maven.org/artifact/ir.tapsell/tapsell) ::: ## Add Container To Your Layout The first step toward displaying a banner is to place a _**`BannerContainer`**_ in the layout of the `Activity` or `Fragment` in which you’d like to display it. The easiest way to do this is to add one to the corresponding `XML` layout file. Here’s an example that shows an activity’s _**`BannerContainer`**_: ```xml title="src/main/res/layout/activity_banner.xml" ``` Alternatively, you can create the _**`BannerContainer`**_ by instantiating it in runtime and adding it to your `ViewGroup`. The `ViewGroup` can be a `FrameLayout` or a _**`AndroidView`**_ of `Jetpack Compose` application: ```kotlin title="create banner container" val container = BannerContainer(context) // Add the container to your ViewGroup ``` ```java title="create banner container" Container container = new BannerContainer(context); // Add the container to your ViewGroup ``` To get more information you can check the full example for Jetpack Compose at the bottom of this tutorial. ## Load Ad Once the BannerContainer is in place, the next step is to load an ad. Banner ads are loaded by calling the `requestBannerAd` static method of the Tapsell class; passing the **zone ID** and a `RequestResultListener` to receive the loaded ad id or possible failure notice. This is usually done in the `onCreate()` method of an `Activity`. ```kotlin title="request method" fun requestBannerAd(zoneId: String, bannerSize: BannerSize, listener: RequestResultListener) ``` ```java title="request method" public static void requestBannerAd(String zoneId, BannerSize bannerSize, RequestResultListener listener) ``` The `RequestResultListener` interface has the following implementation: ```kotlin title="request interface" interface RequestResultListener { // Called when the ad is successfully loaded; providing the ad id needed to show the ad fun onSuccess(adId: String) // Called when there is no ad available fun onFailure(message: String) } ``` ```java title="request interface" interface RequestResultListener { // Called when the ad is successfully loaded; providing the ad id needed to show the ad void onSuccess(String adId); // Called when there is no ad available void onFailure(String message); } ``` :::warning **Applovin, Unity Ads** warning If you intent to load Banner ads from **Applovin** ad-network, you also need to pass an `Activity` instance using the method below: ```kotlin fun requestBannerAd(zoneId: String, bannerSize: BannerSize, activity: Activity, listener: RequestResultListener) ``` ```java public static void requestBannerAd(String zoneId, BannerSize bannerSize, Activity activity, RequestResultListener listener) ``` ::: _**`BannerSize`**_ is an optional `enum` parameter determining the size of the shown ad, with the following values: ```kotlin title="supported banner sizes" enum class BannerSize { BANNER_320_50, // Default value if the parameter is not provided BANNER_320_90, BANNER_320_100, BANNER_250_250, BANNER_300_250, BANNER_468_60, BANNER_728_90, BANNER_160_600, BANNER_ADAPTIVE } ``` ```java title="supported banner sizes" enum BannerSize { BANNER_320_50, // Default value if the parameter is not provided BANNER_320_90, BANNER_320_100, BANNER_250_250, BANNER_300_250, BANNER_468_60, BANNER_728_90, BANNER_160_600, BANNER_ADAPTIVE } ``` Here’s an example that shows how to load an ad in the `onCreate()` method of an `Activity`: ```kotlin title="src/main/java/BannerActivity.kt" showLineNumbers // highlight-start import ir.tapsell.mediation.ad.request.BannerSize import ir.tapsell.mediation.ad.request.RequestResultListener import ir.tapsell.mediation.Tapsell // highlight-end import android.os.Bundle import androidx.appcompat.app.AppCompatActivity class BannerActivity : AppCompatActivity() { companion object { // highlight-next-line private const val ZONE_ID = "SampleZoneId" } // highlight-next-line private lateinit var mBannerContainer: BannerContainer; override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.activity_banner) // highlight-start mBannerContainer = findViewById(R.id.bannerContainer); Tapsell.requestBannerAd(ZONE_ID, BannerSize.BANNER_320_50, object : RequestResultListener { override fun onSuccess(adId: String) { // Ad loaded } override fun onFailure(message: String) { // Ad not available } }) // highlight-end } } ``` ```java title="src/main/java/BannerActivity.java" showLineNumbers // highlight-start import ir.tapsell.mediation.ad.request.BannerSize; import ir.tapsell.mediation.ad.request.RequestResultListener; import ir.tapsell.mediation.Tapsell; // highlight-end public class BannerActivity extends AppCompatActivity { // highlight-next-line private static final String ZONE_ID = "SampleZoneId"; // highlight-next-line private BannerContainer mBannerContainer; protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_banner); // highlight-start mBannerContainer = findViewById(R.id.bannerContainer); Tapsell.requestBannerAd(ZONE_ID, BannerSize.BANNER_320_50, new RequestResultListener() { @Override public void onSuccess(@NonNull String adId) { // Ad loaded } @Override public void onFailure(String message); { // Ad not available } }); // highlight-end } } ``` ## Show Ad Once the banner ad is successfully loaded, the next step is to show the ad. To do so simply call the `showBannerAd()` static method in Tapsell class passing the `adId` received in `onSuccess` method of the `RequestResultListener`. ```kotlin title="show method" fun showBannerAd(adId: String, container: BannerContainer, activity: Activity, listener: AdStateListener.Banner) ``` ```java title="show method" public static void showBannerAd(String adId, BannerContainer container, Activity activity, AdStateListener.Banner listener) ``` The `AdStateListener.Banner` optional parameter can be passed to monitor and handle events related to displaying your Banner ad. The interface has the following implementation: ```kotlin title="Banner show callback" val listener: AdStateListener.Banner = object: AdStateListener.Banner { override fun onAdImpression() { // Code to be executed when an impression is recorded for the ad. } override fun onAdClicked() { // Code to be executed when the user clicks on the ad. } override fun onAdFailed(message: String) { // Code to be executed when the ad show fails. } } ``` ```java title="Banner show callback" AdStateListener.Banner listener = new AdStateListener.Banner() { @Override public void onAdImpression() { // Code to be executed when an impression is recorded for the ad. } @Override public void onAdClicked() { // Code to be executed when the user clicks on the ad. } @Override public void onAdFailed(String message) { // Code to be executed when the ad show fails. } }; ``` ## Destroy Ad When you are done showing your banner ad, you should destroy it so that the ad is properly garbage collected. The example below shows the destroy call in the `onDestroy()` method of an activity: ```kotlin title="src/main/java/BannerActivity.kt" import ir.tapsell.mediation.Tapsell import androidx.appcompat.app.AppCompatActivity class MainActivity: AppCompatActivity() { override fun onDestroy() { Tapsell.destroyBannerAd(adId) super.onDestroy() } } ``` ```java title="src/main/java/BannerActivity.java" import ir.tapsell.mediation.Tapsell; import androidx.appcompat.app.AppCompatActivity; public class MainActivity extends AppCompatActivity { @Override public void onDestroy() { Tapsell.destroyBannerAd(adId); super.onDestroy(); } } ``` Here’s full example for loading and showing an ad in the `Activity`: ```kotlin title="src/main/java/BannerActivity.kt" showLineNumbers package ir.tapsell.sample import android.os.Bundle import androidx.appcompat.app.AppCompatActivity import androidx.annotation.NonNull // highlight-start import ir.tapsell.mediation.Tapsell import ir.tapsell.mediation.ad.AdStateListener import ir.tapsell.mediation.ad.request.RequestResultListener // highlight-end class BannerActivity : AppCompatActivity() { // highlight-start /** * The adId received in `onSuccess` method of the `RequestResultListener`. */ private var adId: String? = null // highlight-end override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.activity_banner) // Your logics ... requestButton.setOnClickListener { requestAd() } showButton.setOnClickListener { showAd() } } override fun onDestroy() { if (adId == null) return // highlight-next-line Tapsell.destroyBannerAd(adId) super.onDestroy() } private fun requestAd() { // highlight-start Tapsell.requestBannerAd(ZONE_ID, BannerSize.BANNER_320_50, object : RequestResultListener { override fun onSuccess(@NonNull adId: String) { this.adId = adId } override fun onFailure(message: String) { // Failed to request ad } }) // highlight-end } private fun showAd() { if (adId == null) return // highlight-start Tapsell.showBannerAd(adId, this, object : AdStateListener.Banner { override fun onAdImpression() {} override fun onAdClicked() {} override fun onAdFailed(@NonNull message: String) {} }) // highlight-end } } ``` ```java title="src/main/java/BannerActivity.java" showLineNumbers package ir.tapsell.sample; import android.os.Bundle; import androidx.annotation.NonNull; import androidx.appcompat.app.AppCompatActivity; // highlight-start import ir.tapsell.mediation.Tapsell; import ir.tapsell.mediation.ad.AdStateListener; import ir.tapsell.mediation.ad.request.RequestResultListener; // highlight-end public class BannerActivity extends AppCompatActivity { // highlight-start /** * The adId received in `onSuccess` method of the `RequestResultListener`. */ private String adId; // highlight-end @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_banner); // Your logics ... requestButton.setOnClickListener(v -> requestAd()); showButton.setOnClickListener(v -> showAd()); } @Override public void onDestroy() { if (adId == null) return; // highlight-next-line Tapsell.destroyBannerAd(adId); super.onDestroy(); } private void requestAd() { // highlight-start Tapsell.requestBannerAd(ZONE_ID, BannerSize.BANNER_320_50, new RequestResultListener() { @Override public void onSuccess(@NonNull String adId) { this.adId = adId; } @Override public void onFailure(String message); { // Failed to request ad } }); // highlight-end } private void showAd() { if (adId == null) return; // highlight-start Tapsell.showBannerAd(adId, activity, new AdStateListener.Banner() { @Override public void onAdImpression() {} @Override public void onAdClicked() {} @Override public void onAdFailed(@NonNull String message) {} }); // highlight-end } } ``` ```kotlin title="src/main/java/BannerActivity.kt" showLineNumbers package ir.tapsell.sample import android.os.Bundle import android.app.Activity import androidx.activity.ComponentActivity import androidx.activity.compose.setContent import androidx.annotation.NonNull import androidx.compose.foundation.layout.* import androidx.compose.material.Button import androidx.compose.material.Text import androidx.compose.runtime.Composable import androidx.compose.runtime.DisposableEffect import androidx.compose.runtime.mutableStateOf import androidx.compose.runtime.remember import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.platform.LocalContext import androidx.compose.ui.unit.dp import androidx.compose.ui.viewinterop.AndroidView // highlight-start import ir.tapsell.mediation.Tapsell import ir.tapsell.mediation.ad.AdStateListener import ir.tapsell.mediation.ad.request.RequestResultListener import ir.tapsell.mediation.ad.request.BannerSize import ir.tapsell.mediation.ad.views.banner.BannerContainer // highlight-end // highlight-next-line private const val ZONE_ID = "SampleZoneId" class BannerActivity : ComponentActivity() { override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContent { BannerScreen() } } } @Composable fun BannerScreen() { // highlight-start val adId = remember { mutableStateOf(null) } val adContainer = remember { mutableStateOf(null) } // highlight-end val activity = LocalContext.current as Activity DisposableEffect(Unit) { onDispose { // highlight-next-line destroyAd(adId.value) } } Column( modifier = Modifier.fillMaxSize().padding(16.dp), horizontalAlignment = Alignment.CenterHorizontally, verticalArrangement = Arrangement.Center ) { Button(onClick = { requestAd { responseId -> adId.value = responseId } }) { Text(text = "Request Ad") } Spacer(modifier = Modifier.height(16.dp)) Button(onClick = { showAd(adId.value, adContainer.value, activity) }, enabled = adId.value != null) { Text(text = "Show Ad") } Spacer(modifier = Modifier.height(16.dp)) Button(onClick = { destroyAd(adId.value) }, enabled = adId.value != null) { Text(text = "Destory Ad") } // highlight-start TapsellBannerView { adContainer.value = it } // highlight-end } } @Composable private fun TapsellBannerView( modifier: Modifier = Modifier, onUpdate: (BannerContainer) -> Unit = {}, ) { val activity = LocalContext.current as Activity val container = BannerContainer(activity) AndroidView( modifier = modifier.fillMaxWidth(), factory = { container } ) onUpdate(container) } private fun requestAd(onSuccess: (String) -> Unit) { // highlight-start Tapsell.requestBannerAd(ZONE_ID, BannerSize.BANNER_320_50, object : RequestResultListener { override fun onSuccess(@NonNull adId: String) { onSuccess(adId) } override fun onFailure(message: String) { // Failed to request ad } }) // highlight-end } private fun showAd(adId: String?, container: BannerContainer?, activity: Activity) { if (adId == null || container == null) return // highlight-start Tapsell.showBannerAd(adId, container, activity, object : AdStateListener.Banner { override fun onAdImpression() {} override fun onAdClicked() {} override fun onAdFailed(@NonNull message: String) {} }) // highlight-end } private fun destroyAd(adId: String?) { if (adId == null) return // highlight-next-line Tapsell.destroyBannerAd(adId) } ``` ## Test Keys To use test app keys and zones, you can refer to the [Test Keys Link](../test) ## Demo Project for more info about implementation, you can find Banner sample for `Java`, `Kotlin` and `Jetpack Compose` on GitHub repository. :::info GitHub Samples - Java - Kotlin - Jetpack Compose ::: ## FAQ If you have any problems regarding implementation of the ads in your project, you can refer to the [FAQ link](../faq) --- # Interstitial Ads Source: https://developer.tapsell.ir/docs/sdk/platforms/android/ad-formats/interstitial Section: Mobile SDK Interstitial ads are full-screen ads that cover the interface of their host app. They’re typically displayed at natural transition points in the flow of an app, such as between activities or during the pause between levels in a game. When an app shows an interstitial ad, the user has the choice to either tap on the ad and continue to its destination or close it and return to the app. This guide shows you how to integrate interstitial ads from Tapsell into your Android app. ## Prerequisite 1. Follow the SDK integration steps described in [Quick start](../quick-start). 2. Make sure you're running the latest Tapsell Mobile Ads SDK version. :::info latest SDK version [![Maven Central](https://img.shields.io/maven-central/v/ir.tapsell/tapsell)](https://search.maven.org/artifact/ir.tapsell/tapsell) ::: ## Load Ad Interstitial ads are loaded by calling the `requestInterstitialAd` static method of the Tapsell class; passing the **zone ID** and a `RequestResultListener` to receive the loaded ad id or possible failure notice. This is usually done in the `onCreate()` method of an `Activity`. ```kotlin title="request method" fun requestInterstitialAd(zoneId: String, listener: RequestResultListener) ``` ```java title="request method" public static void requestInterstitialAd(String zoneId, RequestResultListener listener) ``` The `RequestResultListener` interface has the following implementation: ```kotlin title="request interface" interface RequestResultListener { // Called when the ad is successfully loaded; providing the ad id needed to show the ad fun onSuccess(adId: String) // Called when there is no ad available fun onFailure(message: String) } ``` ```java title="request interface" interface RequestResultListener { // Called when the ad is successfully loaded; providing the ad id needed to show the ad void onSuccess(String adId); // Called when there is no ad available void onFailure(String message); } ``` :::warning **Applovin** warning If you intent to load interstitial ads from **Applovin** ad-network, you also need to pass an `Activity` instance using the method below: ```kotlin fun requestInterstitialAd(zoneId: String, activity: Activity, listener: RequestResultListener) ``` ```java public static void requestInterstitialAd(String zoneId, Activity activity, RequestResultListener listener) ``` ::: Here’s an example that shows how to load an ad in the `onCreate()` method of an `Activity`: ```kotlin title="src/main/java/InterstitialActivity.kt" showLineNumbers // highlight-start import ir.tapsell.mediation.ad.request.RequestResultListener import ir.tapsell.mediation.Tapsell // highlight-end import android.os.Bundle import androidx.appcompat.app.AppCompatActivity class InterstitialActivity : AppCompatActivity() { companion object { // highlight-next-line private const val ZONE_ID = "SampleZoneId" } override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.activity_interstitial) // highlight-start Tapsell.requestInterstitialAd(ZONE_ID, object : RequestResultListener { override fun onSuccess(adId: String) { // Ad loaded } override fun onFailure(message: String) { // Ad not available } }) // highlight-end } } ``` ```java title="src/main/java/InterstitialActivity.java" showLineNumbers // highlight-start import ir.tapsell.mediation.ad.request.RequestResultListener; import ir.tapsell.mediation.Tapsell; // highlight-end public class InterstitialActivity extends AppCompatActivity { // highlight-next-line private static final String ZONE_ID = "SampleZoneId"; protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_interstitial); // highlight-start Tapsell.requestInterstitialAd(ZONE_ID, new RequestResultListener() { @Override public void onSuccess(@NonNull String adId) { // Ad loaded } @Override public void onFailure(String message); { // Ad not available } }); // highlight-end } } ``` ## Show Ad Once the interstitial ad is successfully loaded, the next step is to show the ad. To do so simply call the `showInterstitialAd()` static method in Tapsell class passing the `adId` received in `onSuccess` method of the `RequestResultListener`. ```kotlin title="show method" fun showInterstitialAd(adId: String, activity: Activity, listener: AdStateListener.Interstitial) ``` ```java title="show method" public static void showInterstitialAd(String adId, Activity activity, AdStateListener.Interstitial listener) ``` The `AdStateListener.Interstitial` optional parameter can be passed to monitor and handle events related to displaying your interstitial ad. The interface has the following implementation: ```kotlin title="Interstitial show callback" val listener: AdStateListener.Interstitial = object: AdStateListener.Interstitial { override fun onAdImpression() { // Code to be executed when an impression is recorded for the ad. } override fun onAdClicked() { // Code to be executed when the user clicks on the ad. } override fun onAdClosed(completionState: AdShowCompletionState) { // Code to be executed when the full-screen ad is clicked by the user. } override fun onAdFailed(message: String) { // Code to be executed when the ad show fails. } } ``` ```java title="Interstitial show callback" AdStateListener.Interstitial listener = new AdStateListener.Interstitial() { @Override public void onAdImpression() { // Code to be executed when an impression is recorded for the ad. } @Override public void onAdClicked() { // Code to be executed when the user clicks on the ad. } @Override public void onAdClosed(AdShowCompletionState completionState) { // Code to be executed when the full-screen ad is clicked by the user. } @Override public void onAdFailed(String message) { // Code to be executed when the ad show fails. } }; ``` The `AdShowCompletionState` passed in `onAdClosed` callback, indicates whether the ad has been **shown completely** or **skipped** by the user before completion: ```kotlin title="completion state" enum class AdShowCompletionState { COMPLETED, SKIPPED, UNKNOWN } ``` ```java title="completion state" enum AdShowCompletionState { COMPLETED, SKIPPED, UNKNOWN } ``` Here’s full example for loading and showing an ad in the `Activity`: ```kotlin title="src/main/java/InterstitialActivity.kt" showLineNumbers package ir.tapsell.sample import android.os.Bundle import androidx.appcompat.app.AppCompatActivity import androidx.annotation.NonNull // highlight-start import ir.tapsell.mediation.Tapsell import ir.tapsell.mediation.ad.AdStateListener import ir.tapsell.mediation.ad.request.RequestResultListener import ir.tapsell.mediation.ad.show.AdShowCompletionState // highlight-end class InterstitialActivity : AppCompatActivity() { // highlight-start /** * The adId received in `onSuccess` method of the `RequestResultListener`. */ private var adId: String? = null // highlight-end override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.activity_interstitial) // Your logics ... requestButton.setOnClickListener { requestAd() } showButton.setOnClickListener { showAd() } } private fun requestAd() { // highlight-start Tapsell.requestInterstitialAd(ZONE_ID, object : RequestResultListener { override fun onSuccess(@NonNull adId: String) { this.adId = adId } override fun onFailure(message: String) { // Failed to request ad } }) // highlight-end } private fun showAd() { if (adId == null) return // highlight-start Tapsell.showInterstitialAd(adId, this, object : AdStateListener.Interstitial { override fun onAdImpression() {} override fun onAdClosed(@NonNull adShowCompletionState: AdShowCompletionState) {} override fun onAdClicked() {} override fun onAdFailed(@NonNull message: String) {} }) // highlight-end } } ``` ```java title="src/main/java/InterstitialActivity.java" showLineNumbers package ir.tapsell.sample; import android.os.Bundle; import androidx.annotation.NonNull; import androidx.appcompat.app.AppCompatActivity; // highlight-start import ir.tapsell.mediation.Tapsell; import ir.tapsell.mediation.ad.AdStateListener; import ir.tapsell.mediation.ad.request.RequestResultListener; import ir.tapsell.mediation.ad.show.AdShowCompletionState; // highlight-end public class InterstitialActivity extends AppCompatActivity { // highlight-start /** * The adId received in `onSuccess` method of the `RequestResultListener`. */ private String adId; // highlight-end @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_interstitial); // Your logics ... requestButton.setOnClickListener(v -> requestAd()); showButton.setOnClickListener(v -> showAd()); } private void requestAd() { // highlight-start Tapsell.requestInterstitialAd(ZONE_ID, new RequestResultListener() { @Override public void onSuccess(@NonNull String adId) { this.adId = adId; } @Override public void onFailure(String message); { // Failed to request ad } }); // highlight-end } private void showAd() { if (adId == null) return; // highlight-start Tapsell.showInterstitialAd(adId, activity, new AdStateListener.Interstitial() { @Override public void onAdImpression() {} @Override public void onAdClosed(@NonNull AdShowCompletionState adShowCompletionState) {} @Override public void onAdClicked() {} @Override public void onAdFailed(@NonNull String message) {} }); // highlight-end } } ``` ```kotlin title="src/main/java/InterstitialActivity.kt" showLineNumbers package ir.tapsell.sample import android.os.Bundle import android.app.Activity import androidx.activity.ComponentActivity import androidx.activity.compose.setContent import androidx.annotation.NonNull import androidx.compose.foundation.layout.* import androidx.compose.material.Button import androidx.compose.material.Text import androidx.compose.runtime.Composable import androidx.compose.runtime.DisposableEffect import androidx.compose.runtime.mutableStateOf import androidx.compose.runtime.remember import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.platform.LocalContext import androidx.compose.ui.unit.dp // highlight-start import ir.tapsell.mediation.Tapsell import ir.tapsell.mediation.ad.AdStateListener import ir.tapsell.mediation.ad.request.RequestResultListener import ir.tapsell.mediation.ad.show.AdShowCompletionState // highlight-end // highlight-next-line private const val ZONE_ID = "SampleZoneId" class InterstitialActivity : ComponentActivity() { override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContent { InterstitialScreen() } } } @Composable fun InterstitialScreen() { // highlight-start val adId = remember { mutableStateOf(null) } // highlight-end val activity = LocalContext.current as Activity Column( modifier = Modifier.fillMaxSize().padding(16.dp), horizontalAlignment = Alignment.CenterHorizontally, verticalArrangement = Arrangement.Center ) { Button(onClick = { requestAd { responseId -> adId.value = responseId } }) { Text(text = "Request Ad") } Spacer(modifier = Modifier.height(16.dp)) Button(onClick = { showAd(adId.value, activity) }, enabled = adId.value != null) { Text(text = "Show Ad") } } } private fun requestAd(onSuccess: (String) -> Unit) { // highlight-start Tapsell.requestInterstitialAd(ZONE_ID, object : RequestResultListener { override fun onSuccess(@NonNull adId: String) { onSuccess(adId) } override fun onFailure(message: String) { // Failed to request ad } }) // highlight-end } private fun showAd(adId: String?, activity: Activity) { if (adId == null) return // highlight-start Tapsell.showInterstitialAd(adId, activity, object : AdStateListener.Interstitial { override fun onAdImpression() {} override fun onAdClosed(@NonNull adShowCompletionState: AdShowCompletionState) {} override fun onAdClicked() {} override fun onAdFailed(@NonNull message: String) {} }) // highlight-end } ``` ## Test Keys To use test app keys and zones, you can refer to the [Test Keys Link](../test) ## Demo Project for more info about implementation, you can find Interstitial sample for `Java`, `Kotlin` and `Jetpack Compose` on GitHub repository. :::info GitHub Samples - Java - Kotlin - Jetpack Compose ::: ## FAQ If you have any problems regarding implementation of the ads in your project, you can refer to the [FAQ link](../faq) --- # Native Ads (Banner & Video) Source: https://developer.tapsell.ir/docs/sdk/platforms/android/ad-formats/native Section: Mobile SDK Native ads are ad assets that are presented to users through UI components that are native to the platform. They are shown using the same types This guide shows you how to integrate Native ads from Tapsell into your Android app. ## Prerequisite 1. Follow the SDK integration steps described in [Quick start](../quick-start). 2. Make sure you're running the latest Tapsell Mobile Ads SDK version. :::info latest SDK version [![Maven Central](https://img.shields.io/maven-central/v/ir.tapsell/tapsell)](https://search.maven.org/artifact/ir.tapsell/tapsell) ::: ## Add Container To Your Layout The first step toward displaying a native ad is to create your ad layout using the same views you use in your application. Note that the design and format of the ad layout is completely in your own hands to match your app's design. The only thing you need to consider in your layout design is that **you must put all your ad layout views inside a `NativeAdViewContainer`**, provided by Tapsell SDK: _**`ir.tapsell.mediation.ad.views.ntv.NativeAdViewContainer`**_ is a custom Android `FrameLayout` that must be used as the parent view of the native ad item views. All your ad views providing the content of the ad, like title view, logo view and so on, must be placed inside a **`NativeAdViewContainer`** view. Here's an example that shows an ad layout inside the activity layout: ```xml title="src/main/res/layout/activity_native.xml" ``` **Caution:** If your framework re-renders the DOM, `data-ma-url` handlers may be overwritten. Prefer Method 1 for dynamic UIs. ### Method 4: Scroll Position (`ma-bridge-scroll` or `window.__bridgeScroll`) When the publisher page scrolls, the Loader sends scroll position to your iframe. This is useful for scroll-based animations (e.g., parallax, reveal effects). You can: - Listen for the `ma-bridge-scroll` event: ```javascript document.addEventListener('ma-bridge-scroll', (e) => { const { scrollY, maxScrollY, scrollPercent } = e.detail; // scrollY: current vertical scroll position (px) // maxScrollY: maximum scrollable distance (px) // scrollPercent: 0–100, progress through page scroll // Use scrollPercent to drive animations }); ``` - Or read `window.__bridgeScroll` (updated on each scroll): ```javascript const { scrollY, maxScrollY, scrollPercent } = window.__bridgeScroll || { scrollY: 0, maxScrollY: 0, scrollPercent: 0 }; ``` ### Method 5: Global `window.__bridgeData` (Late-Loading Widgets) If your code runs **after** the `ma-bridge` event has already fired, check `window.__bridgeData`: ```javascript if (window.__bridgeData) { const { recomadLink } = window.__bridgeData; initMyWidget(recomadLink); } // Also listen for the event in case it arrives later document.addEventListener('ma-bridge', (e) => { const { recomadLink } = e.detail; initMyWidget(recomadLink); }); ``` ## Required URL Parameters The Loader injects these query parameters when embedding your custom widget. **Do not** strip them. | Parameter | Description | Example | |-----------|--------------|---------| | `origin` | Publisher domain | `example.com` | | `tagName` | Widget/tag identifier | `mediaad-2vlWn` | Example URL when loaded by Loader: ``` https://your-banner.com/widget?origin=example.com&tagName=mediaad-2vlWn ``` ## Complete Sample (Full HTML) A minimal, self-contained HTML page that imports Bridge, uses the recommended event listener for a CTA button, and displays the publisher's scroll position: ```html Bridge.js Widget Sample ``` Replace `example.com` in the Bridge script URL with your served domain. When loaded inside the Loader's iframe, the button will redirect using the tracked URL, and the scroll div will update as the publisher page scrolls. ## Complete Integration Examples ### Example 1: Vanilla HTML/JS (minimal) ```html Product Banner ``` ### Example 2: React / Solid / Vue (Programmatic CTA) ```tsx // App.tsx (Solid example) function App() { let ctaRef: HTMLButtonElement | undefined; let recomadLink = ''; onMount(() => { const handler = (e: CustomEvent) => { recomadLink = e.detail.recomadLink; if (ctaRef) { ctaRef.onclick = () => recomadLink && window.open(recomadLink, '_blank'); } }; document.addEventListener('ma-bridge', handler as EventListener); return () => document.removeEventListener('ma-bridge', handler as EventListener); }); return (

Order Now

); } ``` ### Example 3: Solid + Vite (Form or CTA component) For a Solid.js project built with Vite: 1. Add Bridge to `index.html`: ```html ``` 2. In your form or CTA component, listen for `ma-bridge`: ```tsx // Form.tsx let recomadLink = ''; onMount(() => { const handler = (e: CustomEvent) => { recomadLink = e.detail.recomadLink || ''; }; document.addEventListener('ma-bridge', handler as EventListener); onCleanup(() => document.removeEventListener('ma-bridge', handler as EventListener)); }); const handleCtaClick = () => { if (recomadLink) window.open(recomadLink, '_blank'); }; ``` ## Troubleshooting ### `ma-bridge` event never fires - **Check URL params:** Ensure `origin` and `tagName` are present. Without them, Bridge cannot request data. - **Check parent:** Your custom widget must run inside an iframe. `window.parent` must be the Loader. - **Check Loader:** The Loader must have data for your widget's `tagName`. ### `recomadLink` is undefined - Creative may not be configured correctly in Mediaad. - Loader may not have received widget data yet. - Inspect `event.detail` in your listener to see what was received. ### CTA does not redirect - Ensure you use `recomadLink` from the event, not a hardcoded URL. - If using `data-ma-url`, verify Bridge runs after your DOM is rendered and that your framework does not remove or replace those elements. ### CORS / Script load errors - Bridge must be served from an allowed domain (e.g., `s1.mediaad.org`). - Confirm the Bridge URL and domain with your Mediaad setup. ### `window.parent` not available - Your page may be running in a top-level window instead of an iframe. The Bridge is intended for iframe contexts only. --- # Loader Source: https://developer.tapsell.ir/docs/web-sdk/loader Section: Web SDK The Loader displays ads on your website. As a **publisher**, you add the Loader script and define where ads should appear. ## How Ads Are Selected {#how-ads-are-selected} The Loader decides which ad should be shown to which user. - Ads come in different formats: video, image, banner, etc. - The selection depends on the user's context: device, browser, and other attributes. ## Integration {#integration} Add the Loader script to your HTML. Replace `{domain}` with your publisher domain (provided by Mediaad). Two options are available: ### Basic Loader {#basic-loader} Simple script for most cases. ```html ``` ### Error Detection {#error-detection} If you need to detect loader failures caused by ad blockers or network issues, use the dedicated [Loader with Error Detection](loader-error-detection) guide. ## Ad Slots (Widgets) {#ad-slots-widgets} Ads appear in predefined slots. Add placeholder elements with a `mediaad-` ID (e.g., `mediaad-12z3`) where you want ads to show. The Loader finds these elements and fills them with the appropriate ad. Example: ```html
``` Your exact widget IDs will be provided by Mediaad. ## Demo & Testing {#demo-testing} Before integrating widgets into your production website, you can explore how Tapsell widgets work on our demo site: **[ads-face.tapsell.ir](https://ads-face.tapsell.ir)** — A publisher demonstration site where you can: - See live examples of different widget types and ad formats - Interact with widgets in a real-world environment - Understand how ads are displayed and formatted - Test and preview widget behavior before implementing them on your website This is a great resource to familiarize yourself with the ad experience and validate that widgets will work well with your website's layout and design. --- # Loader with Error Detection Source: https://developer.tapsell.ir/docs/web-sdk/loader-error-detection Section: Web SDK Use this loader variant when you want to detect failures caused by ad blockers, network issues, or incomplete initialization. ## Integration {#integration} Add the Loader script to your HTML and replace `{domain}` with your publisher domain (provided by Mediaad). ```html ``` ## Error Reasons {#error-reasons} | Reason | When it occurs | |--------|----------------| | `timeout` | Loader script did not finish loading within 15 seconds | | `load_error` | Script failed to load (e.g., blocked by ad blocker, network error) | | `not_initialized` | Script loaded but Mediaad did not initialize within 5 seconds | Return to the main [Loader](loader) guide for the standard setup and widget placement. --- # Retargeting Source: https://developer.tapsell.ir/docs/web-sdk/retargeting Section: Web SDK Retargeting helps you reach users who have visited your website. As an **advertiser**, you add the Retargeting script to your site so we can track relevant user actions and improve your ad campaign targeting. ## Integration {#integration} Add the Retargeting script to the `` section of your website. Replace `{advertiserId}` with your advertiser ID (provided by Mediaad). ```html ``` Example: ```html My Store ``` ## What It Does {#what-it-does} The Retargeting script: - Tracks user interactions on your site (e.g., product views, clicks) - Counts tag occurrences per session - Associates data with Mediaad user IDs for precise retargeting This enables us to serve your ads to users who have shown interest on your website. --- # تمرین با هم فکر کردن Source: https://developer.tapsell.ir/blog/psd-intro Section: Blog تا مدت‌ها فکر می‌کردم یادگیری یعنی تنهاییِ عمیقِ غرق‌شدن در کتاب‌ها. ولی از جایی به بعد، فهمیدم بعضی از مهم‌ترین سؤال‌های فنی رو فقط توی گفت‌وگو با بقیه می‌شه دید و پروروند. از وقتی به تپسل پیوستم، یکی از چیزهایی که توی تیم برای من پررنگ بود، علاقه‌مندی جمعی به یاد گرفتن، بهبود و به اشتراک گذاشتن آموخته‌ها بود. اون هم نه صرفاً در قالب ارائه‌های رسمی، بلکه در فضایی خودمونی و همراه با تعامل. این شد که دوباره یاد دغدغه‌هایی افتادم که شاید مدتی پشت ددلاین‌ها گم شده بودن: مثل اینکه کیفیت یه تصمیم طراحی چقدر می‌تونه مسیر یه پروژه رو عوض کنه، یا اصلاً «کد خوب» یعنی چی وقتی قراره توی یه تیم نوشته و نگه‌داری بشه؟ این شد که یکی از شب‌های خنک و دلچسب اردیبهشت که انسان رو برای زندگی بیشتر به وجد می‌آره، توی تاپیک `Knowledge Sharing` تیم، دو تا کتاب رو پیشنهاد دادم: {/* truncate */}

Cryptography Engineering: Design Principles and Practical Applications

Philosophy of Software Design

خوشبختانه پیشنهاد با استقبال خوبی مواجه شد، و مشخص شد این دغدغه، نه فقط یک دغدغه‌ی شخصی، که یک دغدغه‌ی تیمیه. با مشورت بچه‌های تیم، تصمیم گرفتیم مطالعه‌ی کتاب دوم رو شروع کنیم. قرار شد هر هفته بخشی از کتاب رو بخونیم و یک جلسه‌ی هفتگی داشته باشیم برای بحث و گفت‌وگو درباره‌ی اون بخش. اما چرا این کتاب رو انتخاب کردیم؟ چند دلیل داشتیم: **۱. ساختن یک روتین سبک و منظم برای مطالعه:** شاید این روتین بتونه کمک کنه از دام کمال‌گرایی نجات پیدا کنیم؛ اینکه برای به اشتراک‌گذاری یا یادگیری، لازم نیست همیشه موضوع خیلی پیچیده یا عجیبی مطرح بشه. **۲. زبان ساده و روان کتاب:** باعث می‌شد هم خوندنش آسون‌تر باشه، هم گفت‌وگو راجع بهش. **۳. تمرکز بر مسائل بنیادی ولی مهم:** کتاب ابزار یا تکنیک خاصی یاد نمی‌ده، ولی یک دید خوبی می‌ده که می‌تونه در تصمیم‌های کوچک فنی تأثیرگذار باشه. مثلاً اینکه اگر بشه یه قطعه کد رو به دو روش نوشت، کدوم روش احتمالاً پایدارتر، خواناتر یا قابل‌نگهداری‌تره؟ **۴. نبود جزییات فنی پیچیده:** خوندنش زمان زیادی نمی‌برد و همین باعث می‌شه برای شروع یک حلقه‌ی مطالعه جمعی گزینه‌ی خوبی باشه. اگر تجربه‌ی خوبی بود، می‌تونیم در ادامه سراغ موضوعات عمیق‌تر هم بریم. **۵. نزدیکی مثال‌های کتاب به زبان‌های جاوا و سی:** که باعث می‌شه مثال‌ها ملموس‌تر باشن، چون بخش زیادی از کدهای ما هم به جاوا و کاتلین نوشته شدن. **۶. هم‌زمانی با نیاز تیم به بازبینی کد:** با توجه به عمر پروژه و روندهای اخیر، برخی تسک‌ها مربوط به بازنگری در بخش‌هایی از کد بودن. این کتاب می‌تونست دید بهتری برای انجام این بازبینی‌ها بهمون بده. امیدواریم این تجربه‌ی جمعی، فارغ از نتیجه‌ی نهایی، بتونه برامون شروعی باشه برای بیشتر فکر کردن به طراحی نرم‌افزار، بهتر دیدن کدهایی که می‌نویسیم، و شنیدن صداهای مختلف در مورد مسائل فنی روزمره‌ای که شاید تا حالا از کنارشون بی‌تفاوت رد می‌شدیم. تیم ما مشتاقه که بخش‌هایی از نتیجه‌ی این جلسات رو در بلاگ شرکت منتشر کنه، شاید نه فقط برای مستندسازی مسیرمون، بلکه برای به اشتراک گذاشتن چیزهایی که فکر می‌کنیم برای دیگر تیم‌ها هم مفید یا الهام‌بخش باشن. --- # Taproll; A Faster Ad Player for Android Source: https://developer.tapsell.ir/blog/taproll-intro Section: Blog We've introduced **Taproll**, an Android library for rendering VAST and VMAP video advertisements using native views. It is a drop-in alternative to Google's IMA SDK, designed to keep ads running during connectivity issues or internet access is unavailable. {/* truncate */} ## Why Taproll? Google's IMA SDK is the default choice for VAST/VMAP ad playback on Android, but it has a critical weakness: it requires a persistent internet connection to fetch and render ads. During internet shutdowns, a recurring reality in Iran, IMA-based ad playback breaks entirely. Beyond that, IMA is not prepared for Iran's network conditions, offers no default localization for Farsi, and provides limited control over the ad UI. Taproll was built to address all of these. ### Works During Internet Outages When the internet is shut down, Taproll continues serving ads through intranet without aggressive connectivity checks or reliance on Google services, keeping ad revenue flowing when IMA would fail entirely. ### High Performance Taproll is based on minimal features, lightweightness, minimal footprint, faster builds, and fewer version conflicts. Benchmark results show it starts up and renders the first frame of a pre-roll ad roughly **1.9× faster** than IMA, approximately **1.4s vs 2.65s** under the same conditions. ### Simple UI Control Customize the ad overlay through an XML layout using `XmlOverlayAdapter`, or implement the `AdOverlay` interface for more control over the skip button, countdown timer, and header views. UI elements use standard Android widgets (`TextView` or its subclasses) rather than opaque custom views. ### Low Dependency Taproll's only required dependency is ExoPlayer (Media3). No Google IMA SDK, no Google Play Services, just a single, lightweight library that adds minimal footprint to your build. ### Familiar API, Easy Migration Taproll mirrors IMA's API surface and integration patterns. The `AdsLoader` interface, ad event listeners, and error handling follow the same conventions, so migrating from IMA is mostly a class-name swap. You can even keep both IMA and Taproll side by side — use Taproll as the primary ad loader and fall back to IMA, or vice versa, with zero architecture changes. ### Active Development Taproll is under active development with frequent updates. Need a feature or found a bug? Open a discussion. The team reviews and prioritizes community feedback. ## How It Integrates Taproll integrates with ExoPlayer via `TaprollAdLoader`, which implements the Media3 `AdsLoader` interface. Wire it through `DefaultMediaSourceFactory.setLocalAdInsertionComponents()` and ads play automatically at cue points with zero ad-management code. ```kotlin // ExoPlayer integration: minimal setup val adsLoader = TaprollAdLoader.Builder(context) .setAdEventListener { adEvent -> /* handle event */ } .setAdErrorListener { adError -> /* handle error */ } .build() val player = ExoPlayer.Builder(context) .setMediaSourceFactory( DefaultMediaSourceFactory(context) .setLocalAdInsertionComponents({ adsLoader }, playerView) ) .build() ``` ## Getting Started Taproll is part of **Tapsell Mediation SDK** and fully integrated with it. Add the legacy adapter Taproll integration to your project: ```groovy // build.gradle dependencies { implementation 'ir.tapsell.mediation.adapter:legacy-taproll:$tapsellVersion' } ``` For full setup instructions and ExoPlayer integration details, refer to the Taproll documentation and sample app. --- # Tapsell Maven repository is introduced for Android Developers Source: https://developer.tapsell.ir/blog/tapsell-maven Section: Blog We've introduced **Tapsell Maven** — a dedicated Maven repository and package mirror hosted at `maven.tapsell.ir` — to give Android developers a reliable, fast way to download Tapsell SDKs and all their transitive dependencies without hitting rate limits or connectivity issues with external repositories. {/* truncate */} ## Why Tapsell Maven? Tapsell packages depend on a number of third-party libraries. Fetching all of them from scattered external sources can be slow or unreliable, especially in restricted network environments. By mirroring everything through `maven.tapsell.ir`, you get: - **Single source of truth** — Tapsell SDKs and their dependencies served from one place. - **Faster downloads** — servers are optimised for developers in the region. - **Higher reliability** — no more transient failures from upstream registries. ## Adding the Repository Depending on your project's Gradle setup, add the Tapsell Maven URL in one of the following ways: ```groovy // settings.gradle dependencyResolutionManagement { repositoriesMode.set(RepositoriesMode.FAIL_ON_PROJECT_REPOS) repositories { // Tapsell repository maven { url = uri("https://maven.tapsell.ir") } google() mavenCentral() } } ``` ```groovy // root project build.gradle allprojects { repositories { // Tapsell repository maven { url = uri("https://maven.tapsell.ir") } google() mavenCentral() } } ``` :::tip Kotlin DSL If your project uses Kotlin DSL (`.kts` files), replace `uri("...")` with the same expression — the syntax is identical in both Groovy and Kotlin DSL. ::: ## Next Steps Once the repository is added, follow the full Android SDK setup guide to add the Tapsell dependency to your app module and initialise the SDK: [Android Quick Start — Set up your app](/docs/sdk/platforms/android/quick-start/#set-up-your-app)