# Hướng dẫn cấu hình quảng cáo (Remote Config) — MonetizeD7

Tài liệu **nội bộ** dành cho BA / PO / Ad Ops. Mục đích: **biết cần đặt thiết lập nào trên Firebase, giá trị bao nhiêu, để app hoạt động đúng theo mong muốn kinh doanh**.

**Phiên bản SDK:** `1.1.0` • **Đối chiếu code:** 2026-05-12

---

## Mục lục

1. [Cách hoạt động (đọc 1 phút)](#1-cách-hoạt-động-đọc-1-phút)
2. [Bộ thiết lập mặc định — đầy đủ](#2-bộ-thiết-lập-mặc-định--đầy-đủ)
3. [Chi tiết từng thiết lập](#3-chi-tiết-từng-thiết-lập)
4. [Bảng tra cứu kết quả theo cấu hình](#4-bảng-tra-cứu-kết-quả-theo-cấu-hình)
5. [Changelog phiên bản tài liệu](#5-changelog-phiên-bản-tài-liệu)

---

## 1. Cách hoạt động (đọc 1 phút)

- App **đọc Firebase Remote Config 1 lần** ở màn Splash mỗi khi mở app.
- Sau khi đổi giá trị trên Firebase, người dùng phải **đóng hẳn app rồi mở lại** mới thấy giá trị mới (giá trị bị **giữ cố định** trong suốt 1 phiên dùng app).
- App ở chế độ debug (cho QA): cứ **30 giây** mới đồng bộ lại 1 lần.
- App ở chế độ production (release): **12 tiếng** mới đồng bộ lại (mặc định Firebase).
- Người dùng chia làm **2 nhóm**:
  - **Người dùng mới (FO — First-Open)**: chưa hoàn tất onboarding.
  - **Người dùng cũ (RU — Return User)**: đã hoàn tất onboarding rồi.
  - 2 nhóm dùng **2 bộ thiết lập Splash khác nhau** → cho phép chiến lược khác nhau.
- **Người dùng đã trả phí (premium)** sẽ **không bao giờ** thấy quảng cáo, dù Firebase bật hay tắt.

---

## 2. Bộ thiết lập mặc định — đầy đủ

> Đây là **toàn bộ** thiết lập Firebase mà app đọc, kèm giá trị mặc định khi thiết lập vắng mặt. Khi tạo Firebase project mới: chỉ cần tạo các thiết lập dưới với đúng kiểu và dán giá trị mặc định để mô phỏng hành vi mặc định của SDK.

### 2.1 Bảng tổng — sao chép vào Firebase Console

| # | Tên thiết lập (Firebase) | Kiểu giá trị | Giá trị mặc định |
|---|---|---|---|
| 1 | `fo_banner_splash` | Boolean | `true` |
| 2 | `fo_hf_banner_splash` | Boolean | `true` |
| 3 | `fo_enable_onboarding` | Boolean | `true` |
| 4 | `fo_native_onboarding` | Boolean | `true` |
| 5 | `fo_native_onboarding_2ID` | Boolean | `false` |
| 6 | `fo_allow_log_tester` | Boolean | `false` |
| 7 | `fo_refill_by_ad` | Boolean | `true` |
| 8 | `fo_logic_inter_splash_inc_impression` | Boolean | `false` |
| 9 | `fo_enable_open_ad_on_continue_bar` | Boolean | `true` |
| 10 | `fo_onboarding_config` | String (JSON) | `""` (rỗng → app dùng nội dung trong code) |
| 11 | `fo_config_ad_splash` | String (JSON) | xem §2.2 |
| 12 | `ru_config_ad_splash` | String (JSON) | xem §2.2 (cấu trúc y hệt) |
| 13 | `fo_config_ad_resume` | String (JSON) | xem §2.3 |
| 14 | `inapp_ad_<tên-vị-trí>` | String (JSON) | xem §2.4 — **mỗi vị trí 1 thiết lập riêng** |

> Tổng: **9 thiết lập Boolean + 4 nhóm thiết lập JSON** + N thiết lập `inapp_ad_*` (số lượng tuỳ vào số "vị trí hiển thị ad" mà đối tác đăng ký).

### 2.2 Giá trị JSON mặc định cho `fo_config_ad_splash` & `ru_config_ad_splash`

```json
{
  "is_enabled": true,
  "logic": "variant_1",
  "countdown_seconds": 5,
  "timeout_seconds": 60,
  "native_2id_enabled": false,
  "inter_2id_enabled": false,
  "logic_reload_fallback": false,
  "time_pass_seconds": 0,
  "layout_type": "na_re"
}
```

### 2.3 Giá trị JSON mặc định cho `fo_config_ad_resume`

```json
{
  "is_enabled": true,
  "type": null,
  "layout_type": "na_re",
  "countdown_seconds": 5,
  "time_pass_seconds": 3
}
```

### 2.4 Giá trị JSON mặc định cho mỗi `inapp_ad_<tên-vị-trí>`

Từ SDK `1.1.0`: schema **mới** dạng nested `fo` / `ru` block (gộp luôn rule-show). BA **vẫn phải giữ** các trường legacy phẳng `fo_layout` / `return_layout` để tương thích ngược với các thiết bị còn cài SDK `1.0.0` (xem ghi chú "Dual-shape" cuối §2.4 và §3.6).

```json
{
  "enabled": true,
  "native_enabled": true,
  "inter_enabled": true,
  "ad2id_enabled": true,
  "logic_reload_fallback": false,
  "countdown_seconds": 5,
  "time_auto_pass_second": 0,
  "fo_layout": "na_in",
  "return_layout": "na_in",
  "fo": {
    "layout": "na_in",
    "logic_load_ad": "na_then_in",
    "start": 1,
    "step": 2
  },
  "ru": {
    "layout": "na_in",
    "logic_load_ad": "na_then_in",
    "start": 1,
    "step": 2
  }
}
```

> **Dual-shape (tương thích SDK 1.0.0 ↔ 1.1.0).** Giữ song song cả 2 dạng cho tới khi tỷ lệ cài SDK `1.0.0` < 1%:
> - **SDK 1.0.0** chỉ đọc `fo_layout` / `return_layout` (bỏ qua khối `fo` / `ru`, `ad2id_enabled`, `logic_reload_fallback`, `start`, `step`, `logic_load_ad` — không crash).
> - **SDK 1.1.0** ưu tiên đọc khối nested `fo` / `ru`. Nếu chỉ có flat `fo_layout` / `return_layout` (schema 1.0.0), SDK tự synthesize sang nested với mặc định: `logic_load_ad="na_then_in"`, `start=1`, `step=2`.

### 2.5 Giá trị JSON mặc định cho `fo_onboarding_config` (tuỳ chọn — dùng nếu muốn đổi nội dung onboarding qua Firebase)

Mặc định = chuỗi rỗng → app dùng text + ảnh hardcode trong code. Nếu muốn đổi:

```json
{
  "timePerSlide": 8,
  "slides": [
    {"title": "...", "subtitle": "...", "image": "https://...", "actionLabel": "Next"},
    {"title": "...", "subtitle": "...", "image": "https://...", "actionLabel": "Next"},
    {"title": "...", "subtitle": "...", "image": "https://...", "actionLabel": "Get Started"}
  ]
}
```

### 2.6 Checklist setup Firebase Project mới

- [ ] Tạo 9 thiết lập Boolean (#1–#9 ở §2.1) với giá trị mặc định ở §2.1
- [ ] Tạo 4 thiết lập JSON (#10–#13) — dán JSON mẫu từ §2.2 / §2.3 / §2.5
- [ ] Hỏi đối tác danh sách vị trí hiển thị ad → tạo 1 thiết lập `inapp_ad_<tên>` cho mỗi vị trí, dán JSON §2.4 (giữ cả nested + flat cho tới khi sunset SDK 1.0.0)
- [ ] Bấm **Publish** trên Firebase Remote Config
- [ ] Kiểm tra trong app: bật `fo_allow_log_tester=true` rồi đọc logcat tag `[InAppAd]` để verify

> Nếu **không** tạo thiết lập nào trên Firebase, app vẫn chạy bình thường với giá trị mặc định trên — không bị crash. Chỉ cần tạo trên Firebase **khi muốn đổi giá trị** so với mặc định.

---

## 3. Chi tiết từng thiết lập

### 3.1 Banner Splash

| Tên thiết lập | Kiểu | Mặc định | Tác dụng |
|---|---|---|---|
| `fo_banner_splash` | Bool | `true` | `false` → ẩn banner ở màn Splash |
| `fo_hf_banner_splash` | Bool | `true` | `true` → ưu tiên dùng ID Banner highfloor. `false` → dùng ID thường |

### 3.2 Quảng cáo toàn màn hình ở Splash — cho người dùng mới (`fo_config_ad_splash`)

Tên thiết lập trên Firebase: **`fo_config_ad_splash`** — kiểu String JSON.

| Trường JSON | Kiểu | Mặc định | Giá trị hợp lệ | Tác dụng |
|---|---|---|---|---|
| `is_enabled` | bool | `true` | true / false | **Tắt toàn bộ quảng cáo Splash** — `false` thì không hiển thị quảng cáo toàn màn hình ở Splash |
| `logic` | string | `variant_1` | `variant_1` / `variant_2` / `variant_3` | Chọn cách thử quảng cáo: `variant_1` = Native trước → fail thì Inter; `variant_2` = Inter trước; `variant_3` = Native 2 tầng (highfloor → standard) **không có Inter fallback** (xem §3.2.1) |
| `countdown_seconds` | long (giây) | `5` | >0 | Số giây người dùng phải đợi trước khi nút đóng hiện ra (ngắn = nhẹ UX, dài = giữ user xem lâu hơn) |
| `timeout_seconds` | long (giây) | `60` | >0 | Số giây tối đa app chờ ad load. Dài hơn = nhiều ad fill hơn nhưng splash chậm hơn |
| `native_2id_enabled` | bool | `false` | true / false | `true` → dùng ID Native **highfloor** (áp dụng khi `logic=variant_1` hoặc `variant_3`) |
| `inter_2id_enabled` | bool | `false` | true / false | `true` → dùng ID Interstitial **highfloor** (chỉ áp dụng khi `logic=variant_2`) |
| `logic_reload_fallback` | bool | `false` | true / false | **Chỉ tác dụng với `logic=variant_3`** + `native_2id_enabled=true`: cho phép loader thử cùng lúc HF + Standard trong 1 lần gọi native (giảm chậm khi HF no-fill). Bật khi muốn tối ưu tốc độ Native Dual |
| `time_pass_seconds` | long (giây) | `0` | 0 = tắt, >0 = bật | Tự đóng ad sau N giây (nếu 0 thì user phải tự đóng) |
| `layout_type` | string | `na_re` | `na_preparing` / `na_re` / `na_in` | Kiểu giao diện quảng cáo Native toàn màn hình (xem §3.7) |

#### 3.2.1 Lưu ý quan trọng cho `logic=variant_3` (NATIVE_DUAL)

- Waterfall: `nativeSplash2ID` (highfloor) → `nativeSplash` (standard) → **null** (không hiển thị ad).
- **Không có fallback Interstitial**. Nếu cả 2 tầng native đều fail → splash đi tiếp **không có ad** (skip).
- Yêu cầu đối tác đã cấp `nativeSplash` (ID native standard) ở code-side. Nếu chưa cấp (truyền `""`), chain rút gọn còn `2ID → null`.
- Khuyến nghị **chỉ dùng cho app có inventory native mạnh và chấp nhận đôi lúc không show ad**. Nếu bắt buộc luôn show ad → dùng `variant_1` (có inter fallback) hoặc `variant_2`.
- **Timeout note:** cả 2 tầng dùng chung `timeout_seconds`. HF chạy gần hết timeout có thể "ăn" hết thời gian của standard. Khi bật `variant_3` nên cân nhắc nới `timeout_seconds` hoặc bật `logic_reload_fallback` (nạp song song).

### 3.3 Quảng cáo toàn màn hình ở Splash — cho người dùng cũ (`ru_config_ad_splash`)

Cấu trúc **y hệt** `fo_config_ad_splash` (kể cả `logic=variant_3` và `logic_reload_fallback`). Áp dụng khi user đã hoàn tất onboarding.

> Tách riêng để có thể đặt chiến lược khác nhau giữa người dùng mới (cần ấn tượng mạnh) và người dùng cũ (cần nhẹ nhàng).

### 3.4 Onboarding

| Tên thiết lập | Kiểu | Mặc định | Tác dụng |
|---|---|---|---|
| `fo_enable_onboarding` | Bool | `true` | `false` → bỏ qua onboarding hoàn toàn, vào thẳng Main |
| `fo_native_onboarding` | Bool | `true` | `false` → onboarding không có quảng cáo Native |
| `fo_native_onboarding_2ID` | Bool | `false` | `true` → dùng ID Native highfloor. `false` → dùng ID thường |
| `fo_onboarding_config` | String (JSON) | `""` | Đổi nội dung onboarding qua Firebase (text/ảnh) — không cần build app mới |

**Cấu trúc JSON `fo_onboarding_config`:**

| Trường | Kiểu | Mặc định | Ghi chú |
|---|---|---|---|
| `timePerSlide` | long (giây) | `8` | Tự động giới hạn trong khoảng [2, 30] |
| `slides` | mảng | — | Tối đa 5 slide; nếu rỗng → app dùng text + ảnh trong code |
| `slides[i].title` | string | `""` | Bắt buộc để slide được tính là "hợp lệ" |
| `slides[i].image` | string (URL) | `""` | Bắt buộc — link ảnh trên CDN |
| `slides[i].subtitle` | string | `""` | Tuỳ chọn — nếu để trống thì app dùng text trong code |
| `slides[i].actionLabel` | string | `""` | Tuỳ chọn — nếu để trống app tự đặt `Next` (slide đầu/giữa) hoặc `Get Started` (slide cuối) |

### 3.5 Quảng cáo Resume (khi user mở lại app từ background)

Tên thiết lập trên Firebase: **`fo_config_ad_resume`** — kiểu String JSON.

| Trường JSON | Kiểu | Mặc định | Giá trị hợp lệ | Tác dụng |
|---|---|---|---|---|
| `is_enabled` | bool | `true` | true / false | **Tắt toàn bộ Resume Ad** — `false` thì không hiện quảng cáo khi user mở lại app |
| `type` | string (có thể null) | `null` | `app_open` / `na_fu` | Loại quảng cáo: `app_open` = AppOpen Ad (ngắn), `na_fu` = Native toàn màn hình. Để `null` → app tự chọn theo cấu hình code-side |
| `layout_type` | string | `na_re` | `na_preparing` / `na_re` | Kiểu giao diện (chỉ dùng khi `type=na_fu`) |
| `countdown_seconds` | long (giây) | `5` | >0 | Số giây trước khi nút đóng hiện (chỉ áp Native) |
| `time_pass_seconds` | long (giây) | `3` | 0 = tắt, >0 = bật | Tự đóng ad sau N giây (chỉ áp Native) |

### 3.6 Quảng cáo trong app (InApp) — theo từng vị trí

Mỗi vị trí hiển thị ad trong app (do đối tác đăng ký) có 1 thiết lập riêng tên: **`inapp_ad_<tên-vị-trí>`** — kiểu String JSON.

Ví dụ: `inapp_ad_home`, `inapp_ad_save`, `inapp_ad_share`, `inapp_ad_settings`.

Từ SDK `1.1.0`, schema chuẩn là **nested** (`fo` / `ru` block), kèm các trường legacy phẳng (`fo_layout`, `return_layout`) phải giữ song song để forward-compat với SDK `1.0.0` đang cài trên user thật. Xem ghi chú "Dual-shape" ở cuối §2.4.

#### 3.6.1 Trường top-level

| Trường JSON | Kiểu | Mặc định | Giá trị hợp lệ | Tác dụng |
|---|---|---|---|---|
| `enabled` | bool | `true` | true / false | **Tắt vị trí này** — `false` thì user không thấy quảng cáo ở vị trí đó (action chạy luôn) |
| `native_enabled` | bool | `true` | true / false | `false` → bỏ qua Native, chỉ dùng Interstitial (kết hợp với `logic_load_ad`, xem §3.6.3) |
| `inter_enabled` | bool | `true` | true / false | `false` → bỏ qua Interstitial, chỉ dùng Native |
| `ad2id_enabled` | bool | `true` | true / false | **MỚI 1.1.0** — `false` → bỏ qua thử ID Native highfloor (`NativeAd2Id`), chỉ thử standard. Áp với cả `na_then_in` và `only_na` |
| `logic_reload_fallback` | bool | `false` | true / false | **MỚI 1.1.0** — chỉ tác dụng khi `ad2id_enabled=true` + `logic_load_ad=only_na`: cho phép loader thử cùng lúc HF + Standard trong 1 lần gọi (tối ưu tốc độ) |
| `countdown_seconds` | long (giây) | `5` | >0 | Số giây trước khi nút đóng hiện |
| `time_auto_pass_second` | long (giây) | `0` | 0 = tắt, >0 = bật | Tự đóng ad sau N giây |
| `fo_layout` | string | `na_in` | `na_in` / `na_re` / `na_preparing` | **Legacy (giữ cho SDK 1.0.0)** — Layout cho người dùng mới (FO). SDK 1.1.0 đọc từ `fo.layout` (xem §3.6.2) |
| `return_layout` | string | `na_in` | `na_in` / `na_re` / `na_preparing` | **Legacy (giữ cho SDK 1.0.0)** — Layout cho người dùng cũ (RU). SDK 1.1.0 đọc từ `ru.layout` |

#### 3.6.2 Khối nested `fo` / `ru` (MỚI 1.1.0)

Mỗi block mô tả hành vi riêng cho 1 flow:

| Trường | Kiểu | Mặc định | Giá trị hợp lệ | Tác dụng |
|---|---|---|---|---|
| `layout` | string | `na_in` | `na_in` / `na_re` / `na_preparing` | Layout UI cho flow này (xem §3.7) |
| `logic_load_ad` | string | `na_then_in` | `na_then_in` / `only_na` | Chiến lược waterfall — xem §3.6.3 |
| `start` | int | `1` | `0` = không bao giờ show, `≥1` | Lần đếm impression đầu tiên được show |
| `step` | int | `2` | `≥1` | Show mỗi N lần đếm sau `start`. `1` = mọi lần trigger |

Ví dụ rule-show: `start=2, step=3` → show ở trigger thứ 2, 5, 8, 11, …

#### 3.6.3 Bảng tra cứu `logic_load_ad`

| Giá trị | Hành vi waterfall | Khi dùng |
|---|---|---|
| `na_then_in` (mặc định) | Native HF → fail → Interstitial | Phần lớn touchpoint trong app (case 90%) |
| `only_na` | Native HF → fail → Native standard. **KHÔNG** fallback Interstitial | Surface chỉ chạy native (UX nhẹ, ngại Inter) |

> ⚠️ **Lưu ý cho BA:** với `logic_load_ad=na_then_in`, ID `NativeAdId` (standard) do partner cấp sẽ **bị bỏ qua** — chỉ thử HF (`NativeAd2Id`). Muốn dùng standard, BA phải set `logic_load_ad=only_na`.

### 3.7 Các kiểu giao diện (Layout)

| Giá trị | Mô tả giao diện |
|---|---|
| `na_in` | Native toàn màn hình kiểu chuẩn — bắt mắt, content lớn |
| `na_re` | Native gọn nhẹ kiểu Resume |
| `na_preparing` | Native kiểu "đang chuẩn bị" — countdown hiện từ giây đầu |

> Resume Ad chỉ chấp nhận `na_re` hoặc `na_preparing` (không hỗ trợ `na_in`).

### 3.8 Các thiết lập hành vi khác

| Tên thiết lập | Kiểu | Mặc định | Tác dụng |
|---|---|---|---|
| `fo_allow_log_tester` | Bool | `false` | Bật log chi tiết cho QA debug. **Khi release production → để `false`** |
| `fo_refill_by_ad` | Bool | `true` | `true` → auto reload Native ad sau khi video chạy xong hoặc sau khi user bấm vào ad rồi đóng bottom-sheet (giữ slot luôn có ad). `false` → giữ nguyên ad cũ cho tới khi tự refresh |
| `fo_logic_inter_splash_inc_impression` | Bool | `false` | Chỉ áp **FO user** (chưa hoàn tất onboarding). `true` → cho phép Inter Splash **overlap** với màn tiếp theo (splash chuyển sang Onboarding/Main trong khi Inter vẫn show) → tăng impression. `false` → đợi user đóng Inter xong mới chuyển màn |
| `fo_enable_open_ad_on_continue_bar` | Bool | `true` | Bật/tắt App Open Ad khi user resume từ thanh "Continue" của hệ điều hành. `false` → bỏ qua App Open ở case này |

---

## 4. Bảng tra cứu kết quả theo cấu hình

### 4.1 Splash toàn màn hình (cho cả FO/RU)

| `is_enabled` | `logic` | `native_2id_enabled` | `inter_2id_enabled` | `logic_reload_fallback` | Người dùng thấy gì |
|---|---|---|---|---|---|
| `false` | * | * | * | * | Không có ad — đi thẳng tới onboarding |
| `true` | `variant_1` | `true` | * | * | Native highfloor → nếu fail thì Interstitial thường |
| `true` | `variant_1` | `false` | * | * | Interstitial thường ngay (bỏ qua native) |
| `true` | `variant_2` | * | `true` | * | Interstitial highfloor → nếu fail thì Interstitial thường |
| `true` | `variant_2` | * | `false` | * | Interstitial thường ngay |
| `true` | `variant_3` | `true` | * | `false` | Native HF → fail thì Native standard → fail thì **không có ad** (skip) |
| `true` | `variant_3` | `true` | * | `true` | Loader thử HF + Standard cùng lúc → ưu tiên HF, fail tất cả thì **không có ad** |
| `true` | `variant_3` | `false` | * | * | Native standard ngay → fail thì **không có ad** (skip) |

### 4.2 Onboarding

| `fo_enable_onboarding` | `fo_native_onboarding` | `fo_native_onboarding_2ID` | Người dùng thấy gì |
|---|---|---|---|
| `false` | * | * | Bỏ qua onboarding, vào thẳng Main |
| `true` | `false` | * | Onboarding không có quảng cáo Native |
| `true` | `true` | `false` | Onboarding + Native thường |
| `true` | `true` | `true` | Onboarding + Native highfloor |

### 4.3 Resume Ad

| `is_enabled` | `type` | Người dùng thấy gì |
|---|---|---|
| `false` | * | Không có Resume Ad |
| `true` | `app_open` | AppOpen Ad khi mở lại app từ background |
| `true` | `na_fu` | Native toàn màn hình khi mở lại app |
| `true` | `null` | App tự chọn theo cấu hình code-side |

### 4.4 InApp theo từng vị trí

#### 4.4.1 Bật/tắt tổng & loại ad

| `enabled` | `native_enabled` | `inter_enabled` | `ad2id_enabled` | `logic_load_ad` | Hành vi |
|---|---|---|---|---|---|
| `false` | * | * | * | * | Bỏ qua — không hiện ad ở vị trí này, action chạy luôn |
| `true` | `false` | `false` | * | * | Không có ad (SDK 1.1.0 sẽ tự xem như `enabled=false`) |
| `true` | `true` | `true` | `true` | `na_then_in` | Native HF → fail thì Interstitial (**cấu hình tiêu chuẩn**) |
| `true` | `true` | `false` | `true` | `na_then_in` | Chỉ Native HF — fail thì không có dự phòng |
| `true` | `false` | `true` | * | * | Chỉ Interstitial |
| `true` | `true` | * | `true` | `only_na` | Native HF → fail thì Native standard (**không** thử Inter) |
| `true` | `true` | * | `false` | `only_na` | Bỏ qua HF, dùng Native standard luôn |

#### 4.4.2 Rule-show theo `start` / `step` (trong block `fo` hoặc `ru`)

| `start` | `step` | Show ở các lần trigger |
|---|---|---|
| `0` | * | **Không bao giờ** show |
| `1` | `1` | 1, 2, 3, 4, … (mọi lần) |
| `1` | `2` | 1, 3, 5, 7, … (cấu hình tiêu chuẩn) |
| `2` | `3` | 2, 5, 8, 11, … |

> Counter đếm riêng cho FO và RU, lưu cục bộ trên thiết bị.

---

## 5. Changelog phiên bản tài liệu

> Bám theo [`CHANGELOG.md`](../CHANGELOG.md) của SDK. Mỗi mục liệt kê đúng **những gì BA / Ad Ops phải đổi trên Firebase Remote Config** ở phiên bản đó.

### `1.1.0` — 2026-05-12

**Thêm key Boolean mới (§2.1, §3.8):**
- `fo_refill_by_ad` (mặc định `true`) — auto refill native ad sau end-of-video / sau click bottom-sheet.
- `fo_logic_inter_splash_inc_impression` (mặc định `false`) — chỉ FO user; cho phép Inter Splash overlap màn kế tiếp.
- `fo_enable_open_ad_on_continue_bar` (mặc định `true`) — bật/tắt App Open Ad khi resume từ thanh Continue.

**Đổi schema `fo_config_ad_splash` / `ru_config_ad_splash` (§2.2, §3.2):**
- `logic` thêm giá trị `variant_3` → ánh xạ tới `SplashAdVariant.NATIVE_DUAL` (Native HF → Native standard, **không** có Inter fallback).
- Thêm trường top-level `logic_reload_fallback` (bool, mặc định `false`) — bật song song HF + Standard cho `variant_3`.
- `variant_3` đòi hỏi partner đã cấp `nativeSplash` (ID Native standard) ở code-side. Cấu hình rủi ro skip-ad cao → BA phải align với PO trước khi bật.

**Đổi schema `inapp_ad_<tp>` (§2.4, §3.6) — dual-shape:**
- Schema mới gộp rule-show vào nested block `fo` / `ru` (mỗi block có `layout`, `logic_load_ad`, `start`, `step`).
- Thêm trường top-level: `ad2id_enabled` (bật/tắt thử ID Native highfloor), `logic_reload_fallback` (song song HF+Standard cho `only_na`).
- **Giữ song song** flat keys `fo_layout` / `return_layout` để SDK `1.0.0` còn sống trên user thật vẫn đọc đúng. Chỉ XOÁ flat keys khi tỷ lệ cài SDK `1.0.0` < 1%.
- SDK `1.1.0` có legacy adapter: nếu Firebase chỉ có flat keys (chưa migrate), SDK tự sinh `fo`/`ru` với defaults (`logic_load_ad=na_then_in`, `start=1`, `step=2`) → BA có thể release SDK trước, migrate JSON sau.
- Bỏ key cũ (nếu BA từng tạo trước đây): `inapp_ad_rule_show_<tp>` — đã gộp vào `start`/`step` trong nested block.

**Đổi giá trị mặc định:**
- Không có giá trị mặc định nào thay đổi ngược (back-compat). Mọi mặc định ở §2 giữ nguyên hành vi như 1.0.0 nếu BA không sửa Firebase.

**Action item cho BA khi rollout 1.1.0:**
1. Tạo 3 boolean mới (#7–#9 ở §2.1) trên Firebase với mặc định ở bảng.
2. Nếu muốn thử `variant_3` ở splash → confirm code-side đã có `nativeSplash` rồi mới đổi `logic` JSON sang `variant_3`.
3. Cập nhật mỗi `inapp_ad_<tp>` sang JSON dual-shape ở §2.4 (giữ cả nested + flat).
4. Bấm Publish và verify bằng `fo_allow_log_tester=true` trên build QA.

### `1.0.0` — 2026-04-26

- Phiên bản đầu tiên của tài liệu.
- Schema gốc: `fo_banner_splash`, `fo_hf_banner_splash`, `fo_enable_onboarding`, `fo_native_onboarding`, `fo_native_onboarding_2ID`, `fo_allow_log_tester`, `fo_onboarding_config`, `fo_config_ad_splash`, `ru_config_ad_splash`, `fo_config_ad_resume`, `inapp_ad_<tp>` (schema flat — chỉ có `fo_layout` / `return_layout`).
- `fo_config_ad_splash.logic` hỗ trợ `variant_1` (NATIVE_FIRST) và `variant_2` (INTER_FIRST).
