Partner Resource Form - First Open SDK
Project Information
1, INTEGRATE AD ON LIB:
Link lib: https://github.com/Apero-Partner/MonetizeD7Sample
Version LIB: 1.1.0
Follow guide using : https://md2link.com/d/ddxentdh3efv
2, Ads script
https://docs.google.com/spreadsheets/d/1iGbEWygJeN1loaRUnbzwmNfhlm6gprrLcJzZEdjHBEY/edit?gid=0#gid=0
3, Event Tracking
A. UI, Image, Content First Open Flow
1. UI Colors— colors.xml
The partner will retrieve the Hex Value from the table and pass it to the Resource Name locations in the code.
| Resource Name | Hex Value (Partner fill) | Description |
|---|---|---|
| fo_color_primary | ex:#FFFFFF | Main accent color (buttons, highlights) |
| fo_color_background | Screen background color | |
| fo_color_text_title | Title text color | |
| fo_color_text_sub_title | Subtitle/description text color |
You only need to override the 4 main tokens (the entire SDK UI derives from them):
<resources>
<color name="fo_color_primary">#3B86FF</color>
<color name="fo_color_background">#FFFFFF</color>
<color name="fo_color_text_title">#202020</color>
<color name="fo_color_text_sub_title">#494656</color>
</resources>
2. String Contents— strings.xml
You need to fill the following sections in the code with content
Table explaining the fields that need to be filled in:
| Resource | Description |
|---|---|
| fo_splash_title | @string/app_name |
| fo_onboarding_title_1 | Title of content on OBD1screen |
| fo_onboarding_title_2 | Title of content on OBD2 screen |
| fo_onboarding_title_3 | Title of content on OBD3screen |
| fo_onboarding_description_1 | Subtitle của content trên màn OBD1 |
| fo_onboarding_description_2 | Subtitle của content trên màn OBD2 |
| fo_onboarding_description_3 | Subtitle của content trên màn OBD3 |
<resources>
<string name="fo_splash_title">@string/app_name</string>
<string name="fo_onboarding_title_1">…</string>
<string name="fo_onboarding_title_2">…</string>
<string name="fo_onboarding_title_3">…</string>
<string name="fo_onboarding_description_1">…</string>
<string name="fo_onboarding_description_2">…</string>
<string name="fo_onboarding_description_3">…</string>
</resources>
3. Drawables/Lottie — res/drawable/ and res/raw/
The partner will retrieve the data from the File Provided column in the table and pass it to the Resource Name locations in the code.
Minimum required assets: fo_ic_logo_app + fo_img_onboarding_{1,2,3}.
Partner provides assets with the exact filename (valid extensions: webp, png, jpg):
| Resource Name | File Provided?(Partner fill) | Format | Notes |
|---|---|---|---|
| fo_ic_logo_app | PNG/WebP | App logo for splash | |
| fo_img_splash_bg | |||
| fo_img_onboarding_1 | WebP/PNG | Onboarding 1 image | |
| fo_img_onboarding_2 | WebP/PNG | Onboarding 2 image | |
| fo_img_onboarding_3 | WebP/PNG | Onboarding 3 image | |
| fo_anim_logo_app | raw — Lottie JSON | Animated logo (optional) | |
| fo_anim_onboarding_1 | raw — Lottie JSON | Animated OB1 (optional) | |
| fo_anim_onboarding_1 | raw — Lottie JSON | Animated OB2 (optional) | |
| fo_anim_onboarding_1 | raw — Lottie JSON | Animated OB3 (optional) |
B. Ad Config First Open Flow
0. Add the SDK
settings.gradle.kts:
dependencyResolutionManagement {
repositories {
google()
mavenCentral()
maven {
url = uri("<apero-inhouse maven repo URL>")
credentials {
username = "<provided>"
password = "<provided>"
}
}
}
}
Module app/build.gradle.kts:
dependencies {
implementation("apero-inhouse:monetize-d7:1.1.0")
}
1. Application setup
Create a FirstOpenConfigProvider that builds all ad configs in one place, then register it in Application.onCreate.
class MyFirstOpenProvider : FirstOpenConfigProvider {
override fun provideFirstOpenConfig(): FirstOpenConfig =
FirstOpenConfig.Builder(MyNextActionListener())
.setDevelopment(BuildConfig.DEBUG)
.setSplashAdConfig(
firstOpen = buildSplashConfigFirstOpen(),
returnUser = buildSplashConfigReturnUser(),
)
.setOnboardingAdConfig(buildOnboardingConfig())
.setResumeAdConfig(buildResumeConfig())
.setInAppAd(buildInAppConfig())
.build()
private fun buildSplashConfigFirstOpen(): FirstOpenConfig.SplashAdConfig = TODO("see §1 Splash")
private fun buildSplashConfigReturnUser(): FirstOpenConfig.SplashAdConfig = TODO("see §1 Splash")
private fun buildOnboardingConfig(): FirstOpenConfig.OnboardingAdConfig = TODO("see §2 Onboarding")
private fun buildResumeConfig(): FirstOpenConfig.ResumeAdConfig = TODO("see §3 Resume")
private fun buildInAppConfig(): InAppAdConfig = TODO("see C.4 Inapp Touchpoints")
}
class MyNextActionListener : FONextActionListener {
override fun dispatch(activity: ComponentActivity, intent: Intent) {
val mainIntent = Intent(activity, MainActivity::class.java)
activity.startActivity(mainIntent)
}
}
class MyApp : Application() {
override fun onCreate() {
super.onCreate()
FirstOpenSDK.setFirstOpenConfig(MyFirstOpenProvider())
}
}
setDevelopment(BuildConfig.DEBUG)turns on the Apero Ads tester overlay (load / fail / impression) on debug builds.FONextActionListener.dispatchis where the SDK hands off to the partner's main screen after the FO flow ends.
2. Splash
| # | Slot | Format | BuildConfig field | AD NAME (Compare with “Ad script) file (PO fill) |
|---|---|---|---|---|
| 1 | Splash native splash | Native | NATIVE_SPLASH_HF | |
| 2 | Splash interstitial 2id | Interstitial | INTER_SPLASH_HF | |
| 3 | Splash interstitial | Interstitial | INTER_SPLASH | |
| 5 | Splash banner | Banner | BANNER_SPLASH |
Splash takes two configs — one for first-open (FO), one for return user (RU) — so BA can ship different strategies per segment. Both share the same shape (
FirstOpenConfig.SplashAdConfig).
private fun buildSplashConfigFirstOpen(): FirstOpenConfig.SplashAdConfig {
return FirstOpenConfig.SplashAdConfig(
nativeSplash2ID = NativeAd2Id("ca-app-pub-xxx/fo-native-hf"),
interSplash2ID = InterAd2Id("ca-app-pub-xxx/fo-inter-hf"),
interSplash = InterAdId("ca-app-pub-xxx/fo-inter-standard"),
bannerSplash = BannerAdDouble(
hf = "ca-app-pub-xxx/fo-banner-hf",
standard = "ca-app-pub-xxx/fo-banner-standard",
),
nativeSplash = NativeAdId("ca-app-pub-xxx/fo-native-standard"),
)
}
private fun buildSplashConfigReturnUser(): FirstOpenConfig.SplashAdConfig {
return FirstOpenConfig.SplashAdConfig(
nativeSplash2ID = NativeAd2Id("ca-app-pub-xxx/ru-native-hf"),
interSplash2ID = InterAd2Id("ca-app-pub-xxx/ru-inter-hf"),
interSplash = InterAdId("ca-app-pub-xxx/ru-inter-standard"),
bannerSplash = BannerAdDouble(
hf = "ca-app-pub-xxx/ru-banner-hf",
standard = "ca-app-pub-xxx/ru-banner-standard",
),
nativeSplash = NativeAdId("ca-app-pub-xxx/ru-native-standard"),
)
}
Remote config partner need create on Firebase:
| Key | Value | Description |
|---|---|---|
| fo_banner_splash | true | Turn ad on (Default) |
| false | Turn ad off | |
| fo_enable_onboarding | true | Turn on OBD Screen (Default) |
| false | Turn off OBD Screen | |
| fo_native_onboarding | true | Turn ad on (Default) |
| false | Turn ad off | |
| fo_native_onboarding_2ID | true | Turn ad on |
| false | Turn ad off (Default) | |
| fo_allow_log_tester | true | Turn on Tester log |
| false | Turn off Tester log (Default) |
3. Onboarding
| # | Slot | Format | BuildConfig field | AD NAME (Compare with “Ad script) file (PO fill) |
|---|---|---|---|---|
| 1 | Onboarding native 2id | Native | NATIVE_ONBOARDING_HF | |
| 2 | Onboarding native | Native | NATIVE_ONBOARDING |
Both required.
private fun buildOnboardingConfig(): FirstOpenConfig.OnboardingAdConfig {
return FirstOpenConfig.OnboardingAdConfig(
nativeOnboarding = NativeAdDouble(
hf = "ca-app-pub-xxx/native-onboarding-hf",
standard = "ca-app-pub-xxx/native-onboarding-standard",
),
)
}
4. Resume
| # | Slot | Format | BuildConfig field | AD NAME (Compare with “Ad script) file (PO fill) |
|---|---|---|---|---|
| 1 | App Open Resume | AppOpen | APP_OPEN_RESUME | |
| 2 | Native Resume | Native | NATIVE_RESUME |
Both are optional, but providing both is recommended so the SDK can switch flexibly via Remote Config (fo_config_ad_resume.type).
private fun buildResumeConfig(): FirstOpenConfig.ResumeAdConfig {
return FirstOpenConfig.ResumeAdConfig(
appOpenResume = AppOpenAdId("ca-app-pub-xxx/app-open"),
nativeResume = NativeAdId("ca-app-pub-xxx/native-resume"),
)
}
C. Ad Config InApp Flow
4. Inapp Touchpoints
For each touchpoint in the app, BA must provide 4 pieces of information:
- Touchpoint name (tp) — identifier string the partner uses in code.
- Screen + Trigger — which screen the ad shows on, and what user action triggers it.
- Preload strategy — pick one of two strategies
- 2 ad unit IDs — Native HF + Interstitial (at least one).
| # | Touchpoint (tp) (PO fill) | Screen + Trigger (PO fill) | Preload strategy (PO fill) | NATIVE_<TP> ID AD NAME (Compare with “Ad script) file (PO fill) | INTER_<TP> ID AD NAME (Compare with “Ad script) file (PO fill) |
|---|---|---|---|---|---|
| sample | home | Home screen → user taps "Tools" button → show ad → open Tools screen. Users revisit Home often → reload. | auto-reload | ||
| 2 | result_scr | Result screen → user taps "Share" → show ad → open share sheet. Result is visited once per flow. | one-shot | ||
| 3 | |||||
| 4 | |||||
| 5 |
private fun buildInAppConfig(): InAppAdConfig {
return InAppAdConfig.Builder()
.register(
tp = "home",
nativeAd2Id = NativeAd2Id("ca-app-pub-xxx/home-native-hf"),
nativeAdId = NativeAdId("ca-app-pub-xxx/home-native-standard"),
inter = InterAdId("ca-app-pub-xxx/home-inter"),
)
.register(
tp = "result_scr",
nativeAd2Id = NativeAd2Id("ca-app-pub-xxx/result-native-hf"),
nativeAdId = NativeAdId(""),
inter = InterAdId("ca-app-pub-xxx/result-inter"),
)
.build()
}
Pass an empty id (
NativeAd2Id(""),NativeAdId(""),InterAdId("")) to opt out of a tier. Matching Firebase key per touchpoint:inapp_ad_<tp>.
Preload — in the host Activity.onCreate:
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
InAppAdManager.bindPreload(this, "home")
}
bindPreloadis lifecycle-aware: triggers a preload on everyON_STARTif the pool is empty for that touchpoint, and auto-unregisters onON_DESTROY.
Show — at the trigger site (put navigation / business action inside onNextAction):
InAppAdManager.show(activity, "home") {
startActivity(Intent(this, ToolsActivity::class.java))
}
onNextActionis guaranteed to be called — even when the ad fails,enabled=false, or rule-show skips. Do not run the action outside the lambda — it would run twice.
tp naming rule: snake_case lowercase, no diacritics (home, save_image, share_result). The name must match case-sensitively with the string the partner passes to InAppAdManager.show("...").
ID rule: each touchpoint requires at least one of the two IDs (both Native + Inter, or Native only, or Inter only). Providing both is recommended so the SDK can fall back from Native to Inter when Native has no ad.
Note for partner: for auto-reload → call InAppAdManager.bindPreload(this, "tp") in Activity.onCreate(). For one-shot → call InAppAdManager.preload("tp") once in Activity.onCreate(). See partner-implementation-guide.md §3.