# Partner Resource Form \- First Open SDK

# 

# **Project Information**

### **1, INTEGRATE AD ON LIB:**

**Link lib:** [https://github.com/Apero-Partner/MonetizeD7Sample](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**](https://docs.google.com/spreadsheets/d/1iGbEWygJeN1loaRUnbzwmNfhlm6gprrLcJzZEdjHBEY/edit?gid=0#gid=0)

**3, Event Tracking**

**https://docs.google.com/spreadsheets/d/1iGbEWygJeN1loaRUnbzwmNfhlm6gprrLcJzZEdjHBEY/edit?gid=839304799\#gid=839304799**

---

# **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 |

```xml
<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`:

```kotlin
dependencyResolutionManagement {
    repositories {
        google()
        mavenCentral()
        maven {
            url = uri("<apero-inhouse maven repo URL>")
            credentials {
                username = "<provided>"
                password = "<provided>"
            }
        }
    }
}
```

Module `app/build.gradle.kts`:

```kotlin
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`.

```kotlin
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")
}
```

```kotlin
class MyNextActionListener : FONextActionListener {
    override fun dispatch(activity: ComponentActivity, intent: Intent) {
        val mainIntent = Intent(activity, MainActivity::class.java)
        activity.startActivity(mainIntent)
    }
}
```

```kotlin
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.dispatch` is 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`).

```kotlin
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.*

```kotlin
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).*

```kotlin
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:

1. Touchpoint name (tp) — identifier string the partner uses in code.   
2. Screen \+ Trigger — which screen the ad shows on, and what user action triggers it.  
3. Preload strategy — pick one of two strategies  
4. 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 |  |  |  |  |  |

```kotlin
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`:**

```kotlin
override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)
    InAppAdManager.bindPreload(this, "home")
}
```

> `bindPreload` is lifecycle-aware: triggers a preload on every `ON_START` if the pool is empty for that touchpoint, and auto-unregisters on `ON_DESTROY`.

**Show — at the trigger site (put navigation / business action inside `onNextAction`):**

```kotlin
InAppAdManager.show(activity, "home") {
    startActivity(Intent(this, ToolsActivity::class.java))
}
```

> `onNextAction` is **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.*

