# Yxz Site Data Monetizer

> 基于 GSC 数据驱动补页面 + 接入 AdSense/Adsterra 广告变现，做出"继续做这个站 vs 换下一个游戏词"的明确决策。当游戏站已上线、需要看搜索数据决定补哪些页面、接入广告变现、或判断站点是否值得继续投入时调用。是 yxz-deploy-pipeline 的下游、yxz-game-site-builder 的运营期技能。

- Skill: `byte886/yxz-site-data-monetizer` (Agent Skill, multi-file: 2 files)
- Install (CLI): `npx skillmds@latest add byte886/yxz-site-data-monetizer`
- Raw SKILL.md: https://api.skillmd.com/api/skills/byte886/yxz-site-data-monetizer/raw
- Safety review: pending
- Works with: Claude Code, Claude.ai, OpenAI Codex
- Category: DevOps & Infra
- Author: byte886 (https://skillmd.com/u/byte886)
- Updated: 2026-09-21
- Page: https://skillmd.com/skills/byte886/yxz-site-data-monetizer

---


# 网站数据变现器 (Site Data Monetizer)

> 来源：生财有术航海《AI 产品（国外-热词游戏站）》关卡 6：看数据，补页面、加广告（2026.08.07）
> 引用素材：`images_06/002.png`（GSC 5 指标仪表盘）、`images_06/003.png`（GSC 搜索词报告）、`images_06/004.png`（Adsterra 3 步起步）、`images_06/005.png`（Adsterra 新建广告位表单）、`images_06/006.png`（Banner 468x60 广告代码）、`images_06/007.png`（Native Banner 广告代码）

## 核心原则

**1. 数据决定"继续 vs 换"，不是靠感觉坚持。** GSC 的展示量、点击量、排名、CTR、搜索词就是站点健康度的体检表。展示在涨、有展示有点击 → 继续补；展示有但点击稀烂、连续几周还是个位数访问 → 换下一个游戏词。**大部分游戏站都不赚钱，提前接受这点，避免沉没成本陷阱。**

**2. 第一反应是补页面，不是开新站。** 拿到 GSC 数据后，如果这个词还有搜索流量，**先问"我这个站还缺什么页面"**，而不是"我再去开一个新站"。同一个游戏词上的长尾词承接（codes / build / how to get X / tier list）就是补页面的方向。

**3. 通用词建导航页，个性词建内页。** "xxx best build for Y" 这种每个 Y 对应一个页面太重，做一个统一的"Build 推荐"导航页批量展示即可。"xxx how to get character X" 这种用户带着具体问题来的，做独立内页精准承接。

**4. 广告分两步走：新站先用 Adsterra 跑通变现，日访问过千再切 AdSense。** AdSense 单价高但审核严（缺隐私页/内容少直接拒）；Adsterra 门槛低、审核 1-3 分钟、单价低。新站两三个月内都跑不出大收入，先把变现链路打通再说。

---

## 技能关系

```
yxz-hot-word-miner          → 选定游戏主词
  ↓
yxz-keyword-miner           → 产出关键词清单 + 页面矩阵
  ↓
yxz-game-info-collector     → 产出首页信息 + 内页素材
  ↓
yxz-game-site-builder       → 搭出第一个站
  ↓
yxz-deploy-pipeline         → GA / Vercel / Cloudflare / GSC 上线
  ↓
yxz-site-data-monetizer     ← 本技能：看数据、补页面、加广告、决定继续/换（运营期）
  ↓
（继续路径）yxz-hot-word-miner → 选下一个游戏词开新站
（终止路径）保留模板经验，复用流程
```

> 本技能是 `yxz-deploy-pipeline` 的下游。站点上线后唯一的"看数据→决策→补内容/加广告"运营闭环。

---

## 前置条件

| 必需 | 说明 |
|------|------|
| GSC 域名资源 | 已通过 `yxz-deploy-pipeline` 第四阶段接入 |
| 网站已可正常访问 | 用户能打开页面、能看到广告位 |
| 至少累计 7-14 天数据 | 低于这个时间窗口，GSC 数据噪声大、判断不准 |

| 可选 | 说明 |
|------|------|
| 域名账号 | 已在 spaceship 注册自定义域名（用于 AdSense 申请） |
| Gmail 账号 | 用于注册 AdSense（与 GSC 同 Gmail 最佳） |
| 收款账号 | AdSense 收款需要银行卡或虚拟货币账户 |

---

## 工具与数据获取方式

**所有 GSC / AdSense / Adsterra 后台数据均通过本地浏览器实时抓取**，使用 `mcp_playwright-extension` MCP 服务（server_name = `mcp_playwright-extension`），通过 `run_mcp` 调用。**禁止用 WebFetch/WebSearch 替代**——GSC 与 Adsterra 后台均依赖登录态 + JS 渲染，本地浏览器才能拿到真实数据。

**核心工具调用规范**：

```
# 导航到 GSC / AdSense / Adsterra 后台
run_mcp(server_name="mcp_playwright-extension", tool_name="browser_navigate",
        args={"url": "https://search.google.com/search-console/..."})

# 等待页面/图表渲染（GSC 图表需 4-6 秒）
run_mcp(server_name="mcp_playwright-extension", tool_name="browser_wait_for",
        args={"time": 5})  # 或 {"text": "平均排名"}

# 提取页面文本（用于解析搜索词报告、卡片指标等结构化数据）
run_mcp(server_name="mcp_playwright-extension", tool_name="browser_evaluate",
        args={"function": "() => document.body.innerText.substring(0, 8000)"})

# 截图（GSC 趋势图、AdSense 审核状态、Adsterra 仪表盘等需肉眼判断的场景）
run_mcp(server_name="mcp_playwright-extension", tool_name="browser_take_screenshot",
        args={"type": "png", "scale": "css", "fullPage": false})

# 点击（切换 GSC 时间窗口、勾选 Adsterra 广告格式）
run_mcp(server_name="mcp_playwright-extension", tool_name="browser_click",
        args={"element": "时间窗口按钮", "target": "{snapshot ref}"})

# 填表单（AdSense 申请域名、Adsterra 添加网站）
run_mcp(server_name="mcp_playwright-extension", tool_name="browser_fill_form",
        args={"fields": [{"name":"域名", "target":"...", "type":"textbox", "value":"yourgame.wiki"}]})

# 等待文本出现（确认操作完成，如"已通过审核"）
run_mcp(server_name="mcp_playwright-extension", tool_name="browser_wait_for",
        args={"text": "已通过审核"})
```

**关键技巧**：
- GSC 图表是 SVG，`browser_evaluate` 取 `innerText` 比解析 SVG 更可靠（4 个数据卡 + 搜索词报告都是文本）
- Adsterra 后台的 ad unit 代码是动态生成的，弹出框出现后**等 2-3 秒**再读代码（否则拿到的是空白的 loading 状态）
- AdSense 申请页涉及多步表单（域名 → 地区 → 付款 → 验证），用 `browser_snapshot` 拿当前 step 的 ref，再逐步操作
- **导出 GSC 搜索词用导出按钮**（右上角"导出"按钮 → CSV），比逐条复制更高效；下载到本地后用 Python `pandas` 处理

---

## 执行流程

### 第一阶段：GSC 数据采集与解读

打开 GSC 后台（`https://search.google.com/search-console`）→ 选定域名资源 → 进入"效果"（或"搜索结果"）报告。

#### 步骤 1.1：核对时间窗口

数据是否可信，**取决于时间窗口够不够长**。对照下表选择：

| 时间窗口 | 用途 | 注意点 |
|----------|------|--------|
| **24 小时** | **近实时窗口**：反映当天/昨天的真实点击与曝光（滞后仅数小时） | 与长窗口口径**完全不同**，不单独用于决策；应与长窗口对比看"加速/减速"信号 |
| **7 天** | **补页面决策的首选窗口** | 平衡噪声与时效，反映当前趋势 |
| 28 天 | 看月度趋势、判断是否整体向上 | 用于"换不换词"判断 |
| 3 个月 | 看季节性、长期增长曲线 | 用于"是否值得长期投入"判断 |

**首次看数据建议用 7 天窗口**。低于 7 天的数据基本是噪声，高于 28 天的数据滞后。

> ⚠️ **关键认知：GSC 的「24 小时」是近实时窗口，与「3 个月 / 7 天」不是同一份数据。**
> - **长窗口（3 个月 / 7 天 / 28 天）** = 已处理数据，有 **2–3 天滞后**，统计的是"Google 已算完"的历史。
> - **24 小时窗口** = 近实时数据，覆盖当天及昨天的原始点击/曝光，滞后仅数小时。
> - 同一站点在 24h 窗口的数值**可能远高于长窗口日均**（例如长窗口 7 天累计 0 点击，但 24h 窗口已有 6 点击 / 179 展示）——这不是矛盾，而是长窗口还没处理到最新两天的数据。
> - **新站更要警惕**：新站 GSC 往往只处理了刚被收录那 1–2 天的数据，于是 **3 个月 / 7 天 / 28 天所有长窗口都会坍缩到同一份 2 天数据**（数值完全一致），读不出任何趋势。这是冷启动 + 数据滞后的正常现象，**不是数据错误**。此时 **24 小时窗口才是唯一能反映"最近是否在加速"的信号**。

#### 新站三窗口分析 SOP（推荐每次运营复盘都拉）

> **操作细则（切窗口按钮、等卡片渲染、读数/截图/落盘、判读标准）见 `references/gsc-three-window-capture.md`**——本技能所有 GSC 三窗口 Playwright 抓取动作统一引用该子流程，避免主文件堆代码、也避免多处分叉导致误读。

为区分"长窗口滞后"与"近实时加速"，每次复盘建议拉 **3 个月 / 7 天 / 24 小时** 三档并对照（执行细节见子流程）：

- **长窗口一致、24h 更高** → 站点正在加速（长窗口滞后掩盖了最新增长）。
- **长窗口一致、24h 也低** → 仍处于冷启动停滞期，继续补内容等积累。
- **三档全 0** → 上线不足 2 周或未被收录，过 2 周再查。

#### 步骤 1.2：解读 4 个核心卡片指标

GSC 性能页顶部 4 个卡片是健康度的"血压计"，**只看这 4 个数**（5 个核心维度中第 5 个是搜索词报告，见步骤 1.3）：

| 指标 | 含义 | 健康判断 |
|------|------|----------|
| **总点击次数** | 搜索结果点进网站的次数 | 持续上升 = 内容真的解决问题；连续 7 天 = 0 = 严重信号 |
| **总曝光次数** | 网站在搜索结果中出现次数 | 上升 = 收录增加 / 排名提升；突然下跌 = 可能被算法降权 |
| **平均点击率 (CTR)** | 点击 ÷ 曝光 | 5%-10% 是正常区间；< 3% = 标题/描述不吸引人；> 15% = 标题精准命中需求 |
| **平均排名** | 页面在搜索结果的平均位置 | **< 10 才有意义**；11-30 = 第三页以后基本没人看；> 30 = 边缘流量 |

```
# 提取 4 个卡片数值（示例调用）
run_mcp("mcp_playwright-extension", "browser_evaluate", args={
  "function": "() => { const cards = document.querySelectorAll('[role='region'], .QeOABd, [data-num]'); const text = document.body.innerText; const m = text.match(/总点击次数[\\s\\S]{0,50}?(\\S+)/); const m2 = text.match(/总曝光次数[\\s\\S]{0,50}?(\\S+)/); const m3 = text.match(/平均点击率[\\s\\S]{0,50}?([\\d.]+%)/); const m4 = text.match(/平均排名[\\s\\S]{0,50}?(\\d+\\.?\\d*)/); return { clicks: m?.[1], impressions: m2?.[1], ctr: m3?.[1], avgRank: m4?.[1] }; }"
})
# 返回示例：{ clicks: '4.49万', impressions: '92.8万', ctr: '4.8%', avgRank: '7.1' }
```

> **截图存档**：用 `browser_take_screenshot` 保存 4 个卡片 + 趋势曲线，便于后续复盘对照（见第七阶段复盘表）。

#### 步骤 1.3：导出搜索词报告（最关键的环节）

搜索词报告是**整个 GSC 工作流的核心产出**。它告诉你"用户实际在搜什么词看到你的网站"——其中包含大量你建站时**没想到**的搜索词。每个搜索词都可能是新页面的入口。

```
# 1. 在 GSC 性能页点击 "查询数" 标签（顶部 tab 第二个）
run_mcp("mcp_playwright-extension", "browser_snapshot", args={})
# 从 snapshot 找到 "查询数" tab 的 ref

# 2. 点击后等待表格加载（搜索词表格通常需 3-5 秒）
run_mcp("mcp_playwright-extension", "browser_click", args={
  "element": "查询数 tab",
  "target": "{ref}"
})
run_mcp("mcp_playwright-extension", "browser_wait_for", args={"time": 5})

# 3. 用"导出"按钮下载完整 CSV（推荐）
#    路径：GSC 右上角"导出" → "下载 CSV"
#    下载完成后用 Python pandas 读取：
```

```python
# parse_gsc_queries.py —— 解析 GSC 导出的搜索词 CSV
import pandas as pd
df = pd.read_csv('Queries.csv', skiprows=1)  # GSC CSV 第一行是日期+合计
# 列：顶级查询、展示次数、点击次数、点击率、平均排名
df = df.sort_values('展示次数', ascending=False)
# 输出 top 30 搜索词 + 4 项指标
df.head(30).to_csv('top_queries.csv', index=False, encoding='utf-8-sig')
```

**降级方案**：若导出按钮失效（新版 GSC 偶发），改用 `browser_evaluate` 直接读表格：

```
run_mcp("mcp_playwright-extension", "browser_evaluate", args={
  "function": "() => { const rows = document.querySelectorAll('table tbody tr'); return [...rows].slice(0, 30).map(r => [...r.querySelectorAll('td')].map(td => td.innerText.trim())); }"
})
# 返回二维数组：[查询词, 展示, 点击, CTR, 排名]
```

#### 步骤 1.4：导出页面级报告（看哪些页面有人看）

切换到"网页"标签（顶部 tab 第一个），用同样的方法导出页面级数据。**这告诉你"已做的页面中，哪些真的获得了曝光"**——曝光低的页面要么是选题不对、要么是质量太低。

```
# 切换 tab 后同样用"导出"按钮获取 Pages.csv
# pandas 处理后筛选"展示次数 > 100"的页面（< 100 视为无意义）
df_pages = pd.read_csv('Pages.csv', skiprows=1).sort_values('展示次数', ascending=False)
df_pages[df_pages['展示次数'] > 100].to_csv('useful_pages.csv', index=False, encoding='utf-8-sig')
```

#### 步骤 1.5：判断"哪些搜索词没做对应页面"

把搜索词清单和已有页面交叉比对，**未覆盖的搜索词 = 补页面机会**。

```
# 比对脚本示例
queries = df['顶级查询'].tolist()  # 实际用户搜的词
existing_pages = [...]            # 项目中已有的页面 slug 列表

missing = []
for q in queries:
    # 关键词简化后是否在现有页面中匹配
    simplified = q.lower().replace('the ', '').strip()
    if not any(simplified in p or p in simplified for p in existing_pages):
        missing.append({'query': q, 'clicks': df[df['顶级查询']==q]['点击次数'].iloc[0],
                        'impressions': df[df['顶级查询']==q]['展示次数'].iloc[0],
                        'rank': df[df['顶级查询']==q]['平均排名'].iloc[0]})
```

**输出**：缺失页面机会清单（按展示量降序），进入第二阶段。

---

### 第二阶段：数据驱动补页面（不开新站）

> ⚠️ **第一反应是补页面，不是开新站。** GSC 数据告诉你这个词**还有搜索需求**（有展示），问题只是你的页面没承接住——新开一个站等于把已经积累的收录、权重、外链全部丢弃重来。

#### 步骤 2.1：识别补页面的 3 类信号

从第一阶段的搜索词报告中筛出 3 类信号：

| 信号类型 | 表现 | 动作 |
|----------|------|------|
| **机会词（高展示 + 低排名 + 无对应页面）** | 展示 > 1000，平均排名 > 15，站内无对应页面 | **建新页面**承接 |
| **赢家词（高展示 + 高排名 + 有对应页面）** | 展示 > 500，平均排名 < 10，已有页面 | **做关联内容**扩展（见 2.3） |
| **废词（高展示 + 极低点击 + 平均排名 < 5）** | 标题/描述问题，不是页面问题 | **改 meta**，不建新页 |

#### 步骤 2.2：每类搜索词对应页面类型（来自关卡 6）

按搜索词模式识别要做的页面类型：

| 搜索词模式 | 含义 | 页面类型 | 优先级 |
|------------|------|----------|--------|
| `xxx how to get character X` | 用户想获取某角色/道具 | **获取攻略页** | P1 |
| `xxx best build for Y` | 用户在找最优搭配 | **配装推荐页** | P1 |
| `xxx codes 2026` | 用户在找最新兑换码 | **更新 codes 页**（加年份！） | P0（流量最大） |
| `xxx tier list` | 用户在找分级排行 | **分层榜单页** | P1 |
| `xxx review / is xxx worth it` | 用户在评估游戏 | **评测/介绍页** | P2 |
| `xxx crossplay / multiplayer` | 用户在找联机信息 | **联机指南页** | P2 |
| `xxx release date / price` | 基础信息查询 | **基础信息页**（首页 / FAQ） | P3 |

> **来源**：关卡 6 原文「出现"xxx how to get character X"→ 补一个获取攻略页」「出现"xxx best build for Y"→ 补一个配装推荐页」「出现"xxx codes 2026"→ 更新 codes 页，加上年份」。

#### 步骤 2.3：围绕赢家页做关联内容

识别出"赢家页"（流量稳、排名稳的核心页面）后，**围绕它做 5-10 个关联内容**互相链接，强化主题权威性。

```
# 示例：游戏攻略站的"角色图鉴"页是赢家页
# 围绕它做：
# - 每个主要角色的独立页（10-30 个）
# - 角色配装推荐页
# - 角色对比页（A vs B）
# - 角色获取攻略页
# 全部站内链接到"角色图鉴"页 → 强化主题集群
```

**操作**：
1. 在 `yxz-keyword-miner` 输出的关键词清单中**优先补这一类**长尾词
2. 新建的每个内页都加 1-2 个反向链接到赢家页
3. 赢家页本身增加"相关推荐"区块，链向新建的内页

#### 步骤 2.4：未收录页面诊断与修复

GSC"网页"报告中"展示次数 = 0"的页面，要么没被收录，要么被收录但没排上来。

```
# 用 GSC URL 检查工具逐个排查
# GSC 顶部搜索框 → 输入完整 URL → 回车 → 查看"网址检查"结果

# 三种结果对应不同动作：
# - "网址已编入索引，但目前未在 Google 上展示" → 内容质量低，需重写
# - "网址无法编入索引" → 检查 robots.txt / noindex / 重复内容
# - "网址是重复内容，已选择规范" → 主页面正确，无需处理
```

#### 步骤 2.5：补页面执行（与 yxz-game-site-builder / yxz-game-info-collector 协作）

补页面不是从零开始，而是用现有模板 + 新关键词。流程：

```
1. 用 yxz-keyword-miner 的搜索词清单方法（Google 下拉词 + Trends 相关词 + SEMrush 细分词/问题词 + Ubersuggest 22 细分词 + SimilarWeb Pro 细分词）
   拿到该补页关键词的细分需求清单
2. 用 yxz-game-info-collector 收集该关键词的素材
   （Google 搜索前 2 网页 + YouTube 字幕 + 官网）
3. 用 yxz-game-site-builder 的"内页生成"流程新增一个 MDX/JSX 页面
4. 提交 GSC 请求索引（顶部搜索框输入 URL → 回车 → "请求编入索引"）
```

> **批量补页面**：补 2-3 个页面即可，不要一口气补 10 个。Google 不会因为一次新增 10 个页面就奖励你，反而可能因为"内容质量参差"降权。

> **需求已验证、要规模化铺内页时**：交给 `yxz-bulk-page-factory`——它把本技能产出的 GSC 补页面清单直接变成内页生产线（提示词 + 脚本挂载 + 防灌水相似度/事实密度闸门）。本技能只负责决策"补什么、补哪些词"，批量执行交给它，且必须过它的质量闸门才能上线。

---

### 第三阶段：AdSense 接入（流量起来后的高单价选项）

> AdSense 单价高、长期划算，但审核严、要网站内容够多够正经，适合**日访问 > 500 时**接入。日访问几百时，AdSense 收入可能每天只有几毛到几块。

#### 步骤 3.1：判断接入时机

| 当前日访问 | 建议 |
|------------|------|
| < 100 | 不要接 AdSense（审核很可能不过 + 收入几乎为 0），先用 Adsterra（第四阶段） |
| **100-500** | **可以申请 AdSense**（准备充分大概率能过），同时开 Adsterra 双开 |
| **500-2000** | AdSense + Adsterra 双开，AdSense 放主力位、Adsterra 放次要位补充 |
| > 2000 | AdSense 主力，Adsterra 可关闭（AdSense 单价已显著高于 Adsterra） |

#### 步骤 3.2：审核前自检——确认三个页面齐全（创建由 yxz-game-site-builder 负责）

**本阶段职责是"检查确认"，不是"从头创建"**：三个必备页面（`/about`、`/contact`、`/privacy`）应在 yxz-game-site-builder 建站骨架阶段就已生成（见 yxz-game-site-builder 步骤 1.3）。这里只做核对与补缺。

**自检清单**：
- [ ] `/about` 关于页存在，介绍网站定位、编辑团队、联系方式
- [ ] `/contact` 联系页存在，提供有效的联系邮箱（`mailto:contact@域名`）
- [ ] `/privacy` 隐私政策页存在，≥300 字，覆盖 cookies / 数据收集 / 第三方广告
- [ ] （可选但推荐）`/terms` 服务条款页
- [ ] 至少 5-10 篇内容页（首页不算）

**若缺失**：回到 yxz-game-site-builder 补生成对应页面（不要临时手写一堆就提交）；补完后回到此处重新核对。
**联系邮箱转发**：确认 `contact@域名` 是否能真正收信——见步骤 3.2.1。

> **来源**：关卡 6 原文「审核经常被拒的原因：内容太少、内容质量差、缺隐私页。不要只做一个光秃秃的单页就去申请 AdSense」。

#### 步骤 3.2.1：联系邮箱的 Cloudflare 免费转发配置（按需配置）

**先确认是否需配置**：检查 `contact@<域名>` 是否已能正常收信（发一封测试信到该地址、在真实邮箱确认收到）。若已能收信，跳过本步；若收不到，按下方 Cloudflare Email Routing 免费转发流程配置。

**方案**：用 **Cloudflare Email Routing（免费）** 把域名邮箱转发到你的真实邮箱，无需自建邮件服务器。前提是域名 DNS 托管在 Cloudflare。

```
配置流程（Cloudflare 控制台 → 对应域名 → Email → Email Routing）：
1. 首次进入会要求"启用"Email Routing，并验证一个目标邮箱。
2. 添加「目标地址 / Destination address」：填你的真实邮箱（如 你的QQ邮箱 或 you@example.com）
   → Cloudflare 会发验证邮件到该地址，点邮件里的链接完成验证（状态=Verified）。
3. 添加「路由规则 / Routing rule」：
   - 匹配自定义地址：contact@你的域名
   - 操作：发送到电子邮件（Forward to）→ 选第 2 步验证过的目标地址
   - 保存后规则状态应为「活跃 / Active」
4. 确认 zona 级「Email Routing」总开关=已启用；
   Cloudflare 会自动添加并锁定 3 条 MX（route1/2/3.mx.cloudflare.net）+ SPF + DKIM 记录。
5. 联系页使用 mailto:contact@你的域名 即可。用户发往该地址的邮件会被
   Cloudflare 自动转发到你的真实邮箱。
```

**注意点**：
- 系统默认的「全收→丢弃」catch-all 规则保持「禁用」即可，不影响 `contact@` 这一条具体转发规则。
- 不要直接把联系邮箱写成不存在的地址（如 example.com），AdSense 审核会判为无效联系方式。
- 转发后收件方（如 QQ 邮箱）可能把 Cloudflare 转发件判为可疑，建议把 `contact@你的域名` 加白名单；首封测试信务必先在真实邮箱里确认收到。

**自动化提示（若用 Playwright 配置 Cloudflare Dashboard）**：
Cloudflare Dashboard 大量使用 base-ui（kumo）自定义组件，`browser_click` 常因过渡动画导致元素稳定性超时。统一做法：用 `browser_evaluate` 派发 `PointerEvent`（`pointerdown`+`pointerup`，带 `isPrimary:true` 与元素中心 `clientX/Y` 坐标）展开下拉框，再用 `.click()` 选中 portal 中的选项；选项在 portal 里、不在 combobox 快照树下，要用 `querySelectorAll('[role=option]')` 按文本定位。

> **实测**：已用智能体邮箱（agent-mail）发测试信到 `contact@你的域名`，成功在真实邮箱收到，全链路验证通过。

#### 步骤 3.3：注册与代码集成

```
# 1. 打开 https://adsense.google.com
run_mcp("mcp_playwright-extension", "browser_navigate",
        args={"url": "https://adsense.google.com/start"})

# 2. 登录 Google 账号（与 GSC 同账号最佳，避免关联问题）

# 3. 填写网站 URL（用顶级域名，如 https://yourgame.wiki）
run_mcp("mcp_playwright-extension", "browser_fill_form", args={
  "fields": [{"name":"网站 URL", "target":"...", "type":"textbox", "value":"https://yourgame.wiki"}]
})

# 4. 等待审核（几天到几周不等）
#    - 期间：补内容（每天 1-2 篇）、完善隐私页、添加联系方式
#    - 第一次申请被拒是正常的，修改后重新提交

# 5. 审核通过后 → AdSense 后台 → "广告" → "按广告单元" → 创建展示广告
#    选择"展示广告" + "自适应"尺寸
#    获取代码片段，添加到项目 layout.tsx 中：

# 代码集成（Next.js / React 框架）
# app/layout.tsx <head> 中插入：
<ins className="adsbygoogle"
     style={{ display: 'block' }}
     data-ad-client="ca-pub-{你的发布商 ID}"
     data-ad-slot="{广告单元 ID}"
     data-ad-format="auto" />
<script async src="https://pagead2.googlesyndication.com/pagead/js/adsbygoogle.js?client=ca-pub-{你的发布商 ID}"
        crossOrigin="anonymous"></script>

# 多个广告位：每个 <ins> 配唯一 data-ad-slot
```

**广告位布局建议**（不破坏用户体验）：

| 广告位 | 位置 | 收入贡献 |
|--------|------|----------|
| **文章顶部** | 内页 hero 下方、文章第一段之前 | 最高（用户阅读前注意力集中） |
| **文章中部** | 第二个 H2 小节之后 | 中等（已读用户继续滚动） |
| **侧边栏** | 滚动跟随/固定 | 较低（用户已习惯忽略） |
| **首页 Hero 旁** | 不要！破坏首屏视觉 | 不推荐 |

> **规则**：每页广告位不超过 3 个，超过会触发 AdSense 政策警告。

#### 步骤 3.4：审核与拒审应对

**审核周期**：1 周 - 1 个月，旺季可能更久。**期间不要反复提交**，会被判定为 spam。

**常见拒审原因**：

| 拒审原因 | 修复动作 |
|----------|----------|
| 内容太少 | 补 5-10 篇真实内容页（每篇 800 字以上） |
| 缺隐私页 | 加 `/privacy`，至少 300 字 + 覆盖 cookies/数据/第三方广告 |
| 缺联系方式 | 加 `/contact` 含有效邮箱（不能是 example.com）；域名邮箱用 Cloudflare Email Routing 免费转发到真实邮箱（见步骤 3.2.1） |
| 导航不完整 | 加 `/about` 介绍网站 |
| 内容质量差 | 重写最薄弱的 3-5 个页面 |
| 重复内容 | 检查站内是否有大量相似页面（同一关键词多个页面） |

> **来源**：关卡 6 原文「被拒几次是正常的，补内容再提交」。

#### 步骤 3.5：收款方式选择

AdSense 达到 $100 起付门槛后，需要选收款方式：

| 收款方式 | 手续费 | 适用场景 |
|----------|--------|----------|
| **电汇到国内银行卡** | 单笔 $30+ 固定手续费 | 大金额（> $1000/月） |
| **虚拟货币（Payoneer / Wise）** | 约 2% | 中小金额（< $1000/月） |

> **来源**：关卡 6 原文「电汇到国内银行卡：固定手续费较高，适合大金额 / 虚拟货币方式：约 2% 手续费，适合中小金额」。

新手起步阶段用 Payoneer 虚拟货币账户更划算（手续费低、到账快）。

---

### 第四阶段：Adsterra 接入（新站友好型补充）

> Adsterra 是另一个广告网络，门槛比 AdSense 低、审核快，**新站可以先接它赚第一笔收入**，等流量起来再切 AdSense 或两个一起用。

#### 步骤 4.1：注册 Publisher 账号

```
# 1. 打开 https://www.adsterra.com （或 beta.publishers.adsterra.com）
run_mcp("mcp_playwright-extension", "browser_navigate",
        args={"url": "https://beta.publishers.adsterra.com/"})

# 2. 点击"注册" → 选 Publisher（不是 Advertiser）
# 3. 填写邮箱 + 设置密码 → 完成邮箱验证

# 4. 登录后进入 Publishers Dashboard
run_mcp("mcp_playwright-extension", "browser_wait_for", args={"text": "Publishers"})
```

**注意**：
- 一个邮箱只能注册一个 Publisher 账号
- 注册信息中的网站 URL 要用顶级域名（不要用 Vercel 默认域名，会被拒）
- 注册信息真实（姓名、地址），后续收款会用到

#### 步骤 4.2：添加网站 + 创建广告位

**添加网站步骤**：

```
# 1. 进入 Publishers Dashboard → 点击 "ADD WEBSITE"
run_mcp("mcp_playwright-extension", "browser_click", args={
  "element": "ADD WEBSITE 按钮",
  "target": "{ref from snapshot}"
})

# 2. 在弹出框填写：
#    - Website: https://yourgame.wiki
#    - Website category: Games（或最接近的类别）
#    - Show adult ads: 默认关（开的话 CPM 高但用户体验差，违反 AdSense 政策）
#    - Choose Ad Unit format: 见下方推荐

# 3. 点击 ADD 提交
```

**广告格式选择**（来自关卡 6 原文）：

| 格式 | 推荐度 | 原因 |
|------|--------|------|
| **Native Banner** | ⭐⭐⭐⭐⭐ | 原生横幅、体验温和、不打扰阅读 |
| **Banner** | ⭐⭐⭐⭐ | 最简单、容易集成，但视觉突兀 |
| Social Bar | ⭐⭐⭐ | 弹条样式，转化高但轻度打扰 |
| Popunder | ⭐⭐ | **新站不推荐**——太激进、影响用户体验、易触发广告拦截 |

> **来源**：关卡 6 原文「新手推荐『Native Banner』（原生横幅，体验温和）或『Banner』（最简单）；先别选 Popunder 弹窗，太激进、影响用户体验」。

#### 步骤 4.3：等待审核 + 获取广告 Key

```
# 1. 提交后等待 1-3 分钟（远超 AdSense 的几天到几周）
run_mcp("mcp_playwright-extension", "browser_wait_for", args={"time": 3})

# 2. 刷新页面，确认 Website status 显示"Active"
run_mcp("mcp_playwright-extension", "browser_evaluate", args={
  "function": "() => { const text = document.body.innerText; return text.match(/Active|Inactive|Pending/i)?.[0]; }"
})

# 3. 进入 Website → Ad Units → 创建广告单元
#    每个广告单元生成后，Adsterra 分配唯一 Key（32 位十六进制字符串）
#    如 Banner 468x60 的 key: c0c99ae30cae72d3c78191a29dd6a6fe
```

**广告 Key 类型**：

| 广告类型 | Key 形态 | 代码形态 |
|----------|----------|----------|
| **Banner** | `c0c99ae30cae72d3c78191a29dd6a6fe`（32 位 hex） | JS 配置对象（atOptions + invoke.js） |
| **Native Banner** | `bd94db4b047c4527c4d968a4531133b7`（32 位 hex） | 异步 script + div container |

**Banner 代码示例**（来自 `images_06/006.png`）：

```html
<script>
  atOptions = {
    'key' : 'c0c99ae30cae72d3c78191a29dd6a6fe',
    'format' : 'iframe',
    'height' : 60,
    'width' : 468,
    'params' : {}
  };
</script>
<script src="https://www.topcreativeformat.com/{你的广告KEY}/invoke.js"></script>
```

**Native Banner 代码示例**（来自 `images_06/007.png`）：

```html
<script async="async" data-cfasync="false"
  src="https://turbulentrefreshments.com/{你的广告KEY}/invoke.js">
</script>
<div id="container-bd94db4b047c4527c4d968a4531133b7"></div>
```

#### 步骤 4.4：代码集成到项目（推荐用环境变量）

> **来源**：关卡 6 原文「你需要让大模型，在代码中引用这些脚本，appkey 可以通过环境变量传入」。

```
# 项目目录结构建议
├── .env.local.example          # 环境变量示例
├── components/
│   ├── AdsterraBanner.tsx      # Banner 广告组件
│   ├── AdsterraNative.tsx      # Native Banner 广告组件
│   └── AdSenseUnit.tsx         # AdSense 广告组件

# .env.local（真实配置）
NEXT_PUBLIC_ADSTERRA_BANNER_KEY=c0c99ae30cae72d3c78191a29dd6a6fe
NEXT_PUBLIC_ADSTERRA_NATIVE_KEY=bd94db4b047c4527c4d968a4531133b7
NEXT_PUBLIC_ADSENSE_PUB_ID=ca-pub-1234567890123456
NEXT_PUBLIC_ADSENSE_SLOT_TOP=1234567890
```

**React 组件示例**（`components/AdsterraBanner.tsx`）：

```tsx
'use client';

export default function AdsterraBanner() {
  const key = process.env.NEXT_PUBLIC_ADSTERRA_BANNER_KEY;
  if (!key) return null;

  return (
    <div className="my-6 flex justify-center">
      <script
        dangerouslySetInnerHTML={{
          __html: `
            atOptions = {
              'key' : '${key}',
              'format' : 'iframe',
              'height' : 60,
              'width' : 468,
              'params' : {}
            };
          `,
        }}
      />
      <script
        async
        src={`https://www.topcreativeformat.com/${key}/invoke.js`}
      />
    </div>
  );
}
```

**集成位置**：

```tsx
// app/[lang]/layout.tsx 或 app/layout.tsx
import AdsterraBanner from '@/components/AdsterraBanner';
import AdSenseUnit from '@/components/AdSenseUnit';

// 内页文章顶部（Hero 下方）
export default function ArticleLayout({ children }) {
  return (
    <>
      <Navbar />
      <Hero />
      <AdsterraBanner />   {/* 第一个广告位 */}
      <article>{children}</article>
      <AdSenseUnit slot="TOP" />  {/* 第二个广告位 */}
      <Footer />
    </>
  );
}
```

**Vercel 部署配置**：

```
# 在 Vercel Project Settings → Environment Variables 添加：
NEXT_PUBLIC_ADSTERRA_BANNER_KEY = {你的 key}
NEXT_PUBLIC_ADSTERRA_NATIVE_KEY = {你的 key}
NEXT_PUBLIC_ADSENSE_PUB_ID = {你的发布商 ID}
NEXT_PUBLIC_ADSENSE_SLOT_TOP = {广告单元 ID}
# Environment: 勾选 Production + Preview + Development
```

#### 步骤 4.5：广告开始展示 + 收益监控

审核通过后立即生效，无需等待。收益监控在 Adsterra 后台 → Statistics 查看。

**收入预期**（来自关卡 6 原文）：

| 日访问量 | AdSense 单日收入 | Adsterra 单日收入 |
|----------|------------------|-------------------|
| 几十 | $0（达不到起付门槛） | $0.1-0.5（仍极低） |
| 几百 | $0.5-3 | $0.3-2 |
| 1000-5000 | $3-15 | $2-8 |
| > 10000 | $15-50 | $8-25 |

> **来源**：关卡 6 原文「日访问几百的时候，AdSense 收入可能每天只有几毛到几块钱」。

**别被收入打消积极性**——前期收入就是象征性的，**真正价值是验证变现链路完整 + 用户点击习惯**。

---

### 第五阶段：AdSense vs Adsterra 选型与组合

#### 步骤 5.1：横向对比

| 维度 | AdSense | Adsterra |
|------|---------|----------|
| **CPM / CPC 单价** | 高（多数品类 2-5x Adsterra） | 中低 |
| **审核周期** | 几天到几周（旺季更长） | **1-3 分钟** |
| **审核严格度** | 严（缺隐私页/内容少直接拒） | 宽松 |
| **新站友好度** | 差 | **极佳** |
| **起付门槛** | $100 | $5（Payoneer）/ $100（电汇） |
| **广告主质量** | 高（Google 严格审核广告主） | 中（含部分成人/博彩广告，需手动关） |
| **支付稳定性** | 极稳 | 稳 |
| **技术支持** | 完善 | 邮件支持（响应慢） |

#### 步骤 5.2：组合策略（按站点阶段）

| 站点阶段 | 推荐方案 |
|----------|----------|
| **新站（日访问 < 100）** | **只接 Adsterra**——AdSense 大概率审核不过，且即使过审收入也几乎为 0 |
| **成长期（日访问 100-1000）** | **Adsterra 为主**，申请 AdSense 储备 |
| **稳定期（日访问 1000-5000）** | **双开**——AdSense 主力位（文章顶部）+ Adsterra 次要位（侧边栏/底部） |
| **成熟期（日访问 > 5000）** | **AdSense 为主**，Adsterra 可关闭（AdSense 单价已显著高于 Adsterra） |

> **来源**：关卡 6 原文「新站先用 Adsterra 起步 → 日访问过千、AdSense 能过审了再切 AdSense（或两个一起用——AdSense 放主力广告位，Adsterra 放次要位补充收入）」。

#### 步骤 5.3：双开的注意事项

```
- AdSense 单页最多 3 个广告位（超过会被 policy 警告）
- Adsterra 单页不限，但太多会触发广告拦截器
- 双开时把 AdSense 放用户最可能注意的位置（文章顶部、中部），Adsterra 放边缘位置（侧边栏、文章底部）
- 观察两个广告网络的 CTR：若 AdSense < Adsterra，可能是 AdSense 广告与内容相关性差，检查广告类别过滤设置
```

---

### 第五·五阶段：GA4 流量质量校验（决策前置，必做）

> ⚠️ **在做任何「继续/换站」或「加广告」决策前，必须先确认流量是真的。** GSC 只统计来自 Google 搜索的真实展示与点击，天然干净；但 GA4 统计的是**所有到达站点的访问**，其中包含机器人、扫描器、以及运营者自己的调试访问。新站尤其严重——未经校验的 GA 数据可能九成是噪声，据此决策会得出完全相反的结论。

#### 步骤 5.5.1：抓取 GA4 首页卡片

GA4 首页 URL 形如 `https://analytics.google.com/analytics/web/#/a{account}p{property}/reports/intelligenthome`。

- 导航后必须 `browser_wait_for` 约 **5 秒**等 SPA 渲染。判断依据：页面标题从 `Analytics` 变为 `Google Analytics | 首页` 才算加载完成。
- 数据可直接用 `document.body.innerText` 整段取出，**无需穿透 Shadow DOM**（GA4 的 shadowRoot 只装 CSS）。

需要记录的字段：活跃用户、新用户数、事件数、关键事件数、各国家活跃用户、各渠道会话数、来源/媒介、事件名称分布、网页标题浏览次数。

#### 步骤 5.5.2：判断流量真实性（核心）

**红旗信号**（命中 2 条以上即认定数据不可信）：

| 信号 | 含义 |
|---|---|
| Direct + Unassigned 占比 > 60% | 新站不可能有大量真实"直接访问"，多为无 referrer 的机器人 |
| 出现 `vercel.com / referral`、`netlify.app / referral` | 运营者从部署面板点进来的自访问 |
| 有与目标市场语言不符的国家（如英文站出现中国区用户） | 高度疑似运营者本人 |
| Russia / Poland / Vietnam 等无对应内容语言的国家占比异常 | 典型爬虫/代理来源 |
| 出现 `/analytics.js`、`/atom.xml`、`/wp-login.php`、`/xmlrpc.php`、含 `+` 等畸形字符的路径 | 扫描器在探测常见路径 |
| 新用户数 = 活跃用户数 | 零回访，正常但需与上述信号合并解读 |

**校验方法**：把 GA4 的 `google / organic` 会话数与 GSC 的点击数做交叉验证。两者应大致同量级；若 GA 总会话数是 organic 的 10 倍以上，说明绝大部分流量并非来自搜索。

> **判定口径**：`google / organic` 的会话数才是**真实外部自然流量**的规模，「继续/换站」与「加广告」决策应只依据这个数字，而非 GA 首页显示的活跃用户总数。

#### 步骤 5.5.3：切到路径维度定位问题页

**GA4 默认的「网页标题和屏幕类」维度会掩盖问题**——所有 404 都被合并成一行「404: This page could not be found.」，看不出是哪些 URL 在报错。

**必须换成路径维度**。改 URL 比点 UI 稳定：

```
https://analytics.google.com/analytics/web/#/a{account}p{property}/reports/explorer
  ?params=_u..nav%3Dmaui
    %26_r.explorerCard..selmet%3D%5B%22screenPageViews%22%5D
    %26_r.explorerCard..seldim%3D%5B%22unifiedPagePathScreen%22%5D
  &r=all-pages-and-screens
```

- `unifiedPagePathScreen` = 网页路径（要的）；`unifiedScreenClass` = 网页标题（默认，不够用）
- 翻页：找 `aria-label=下一页` 的 button 点击，URL 会追加 `%26_r.explorerCard..startRow%3D10`
- 拿到路径表后，把各 404 路径的浏览次数相加，应当等于标题维度里「404」那一行的数值——**对上账就说明 404 来源已完全定位**

#### 步骤 5.5.4：读互动时长的落差

对比首页与内页的**平均互动时长**，这是区分机器人与真人最有效的单一指标：

- 首页停留 < 5 秒、内页停留 > 15 秒 → 机器人抓首页即走，真人集中在深度内页；同时说明**首屏缺少即时价值**，应把高互动内页的内容前置到首页首屏
- 某内页停留 1-2 秒（显著低于同类内页） → 该页内容单薄或与搜索意图错配，优先重写或合并

辅助指标：滚动率 = `scroll` 事件数 / `page_view` 数（健康值 > 35%）；页/会话 = `page_view` / `session_start`。

#### 步骤 5.5.5：数据可信化整改（P0）

确认存在噪声后，**先整改再看数据**，否则后续所有复盘都失真：

1. **配置内部流量过滤**：GA4 管理 → 数据流 → 更多标记设置 → 定义内部流量，填入自己的 IP；再到「数据设置 → 数据过滤」把 `Internal Traffic` 过滤器从「测试」改为**「有效」**（默认是测试状态，不会真正生效，这一步最容易漏）
2. **排除部署平台 referral**：把 `vercel.com` / `netlify.app` 加入「排除的引荐来源」
3. **配置关键事件**：关键事件为 0 意味着没有任何商业衡量标尺。广告站建议至少配 4 个——外链跳转（Steam 等）、滚动深度 90%、停留 ≥30 秒、广告点击

#### 步骤 5.5.6：把 GA 结论并回变现决策

| GA 校验结果 | 对「加广告」的判断 |
|---|---|
| 真实 organic 会话 < 10 / 周 | **暂不加广告**。AdSense 会因内容/流量不足被拒；Adsterra 收入趋近 $0，且广告位会拖慢本就很低的首页停留。当前矛盾是「让真实流量进来」而非「怎么变现」 |
| 真实 organic 会话 10-100 / 周 | 可上 Adsterra 跑通链路，但不要期待收入 |
| 真实 organic 日点击 > 20 | 进入正常变现节奏，按第三/四阶段执行 |

> **分析说明**：这一阶段的价值在于**避免用假数据做真决策**。一个"70 活跃用户"的站看起来值得马上加广告，但如果其中只有 4 个来自自然搜索，真实结论是"还在冷启动期，应该继续补内容"——两者的行动方向完全相反。

---

### 第六阶段：继续 vs 换站决策

> ⚠️ **大部分游戏站都不赚钱，提前接受这点。** 决策不是"如何让每个站都成功"，而是"如何在 1-2 个站里识别有戏的、果断放弃没戏的"。

#### 步骤 6.1：继续信号（这个站值得补）

**4 个强信号**（任意 2 个满足即可继续）：

1. **数据在涨**——过去 28 天展示量 / 点击量持续上升（截图存档对比）
2. **有展示有点击**——平均排名 < 30，至少有 3-5 个搜索词带来展示
3. **有广告收入**——即使每天 $0.5，也证明用户愿意停留、变现链路完整
4. **新词机会持续出现**——GSC 每周都有新搜索词涌入（说明游戏仍在热度期）

**继续做的话，做什么**：

- 补更多页面，扩大关键词覆盖（第二阶段流程）
- 接入 AdSense 提升单价（第三阶段流程）
- 把建站流程做成自己的模板（`yxz-game-site-template-maker`），下一个站更快上线

#### 步骤 6.2：换站信号（这个站放弃，换下一个游戏词）

**4 个强信号**（任意 2 个满足即可换）：

1. **有展示没点击**——平均排名 < 20 但 CTR < 1%（说明标题/描述问题，但用户需求可能是错的）
2. **多个星期还是每天个位数访问**——意味着关键词热度已过、或竞争太强
3. **新词机会枯竭**——GSC 搜索词报告 2 周没新增
4. **GSC 趋势持续下降**——28 天展示量比上 28 天低 50%+

**换站时做什么**：

- **保留这个站的模板和流程经验**——不要直接关站，留着看 AdSense 能否补审
- **用同样流程换一个游戏词**——第二次会快很多，因为模板已就位
- **检查是不是内容没真正回答用户的问题**——常见原因：抄了对标站但抄歪了、缺关键攻略、英文不地道

> **来源**：关卡 6 原文「不丢人——大部分站都不赚钱」。

#### 步骤 6.3：决策记录

每次做"继续 / 换站"决策时，写一行决策记录（不要只记在脑子里）：

```markdown
## 决策记录 - {日期}

**站点**：{yourgame.wiki}
**当前阶段**：上线第 {N} 周
**过去 28 天数据**：
- 总曝光：{N}
- 总点击：{N}
- 平均排名：{N}
- 广告收入：${N}

**判断依据**：
- [信号 1]: [满足/不满足]
- [信号 2]: [满足/不满足]
- [信号 3]: [满足/不满足]
- [信号 4]: [满足/不满足]

**决策**：[继续 / 换站]
**理由**：[具体说明]
**下一步动作**：[继续的话要补什么 / 换的话用什么模板换什么词]
```

---

### 第七阶段：数据复盘表填写

> 关卡 6 末尾提供的"对着填"复盘表。每次运营决策前过一遍这个表，相当于给站点做一次体检。

**模板**（`{日期}-{游戏主词}-数据复盘.md`）：

```markdown
# {游戏主词} 数据复盘

> 复盘日期：{YYYY-MM-DD}
> 站点：{yourgame.wiki}
> 统计时间段：{起始日} → {结束日}（建议 28 天）

## 核心指标

| 指标 | 数值 | 趋势（vs 上 28 天） |
|------|------|---------------------|
| 总展示量 | {N} | ↑/↓/→ |
| 总点击量 | {N} | ↑/↓/→ |
| 平均排名 | {N} | ↑/↓/→ |
| 平均点击率 | {N}% | ↑/↓/→ |
| 广告收入 | ${N} | ↑/↓/→ |

## Top 5 搜索词

| 排名 | 搜索词 | 展示 | 点击 | CTR | 排名 |
|------|--------|------|------|-----|------|
| 1 | {query} | {N} | {N} | {N}% | {N} |
| 2 | {query} | {N} | {N} | {N}% | {N} |
| 3 | {query} | {N} | {N} | {N}% | {N} |
| 4 | {query} | {N} | {N} | {N}% | {N} |
| 5 | {query} | {N} | {N} | {N}% | {N} |

## 出现了哪些没做页面的词

| 搜索词 | 展示 | 排名 | 计划做的页面 |
|--------|------|------|--------------|
| {query} | {N} | {N} | {说明} |
| ... | ... | ... | ... |

## 哪些页面没被收录

| URL | 状态 | 原因 | 修复动作 |
|-----|------|------|----------|
| {/path} | 未收录 / 收录未展示 | {说明} | {说明} |

## 下一步要补的 2-3 个页面

1. {页面名 + URL + 对应搜索词}
2. {页面名 + URL + 对应搜索词}
3. {页面名 + URL + 对应搜索词}

## 决策

- [ ] 继续补这个站（依据：{信号}）
- [ ] 换下一个游戏词（依据：{信号}）

## 广告变现状态

- [ ] Adsterra 已接入（Native Banner / Banner）
- [ ] AdSense 已申请 / 已通过 / 被拒（{N} 次）
- [ ] 过去 28 天广告收入：${N}
```

---

## 输出文件

执行完成后产出：

1. **GSC 数据快照**：`{日期}-{游戏主词}-GSC快照/`（含 4 卡片截图 + 趋势曲线截图）
2. **搜索词报告**：`{日期}-top_queries.csv`（导出原始 CSV）
3. **页面机会清单**：`{日期}-{游戏主词}-补页面清单.md`（来自步骤 1.5）
4. **数据复盘文档**：`{日期}-{游戏主词}-数据复盘.md`（第七阶段模板）
5. **广告接入配置**：
   - `.env.local` / `.env.local.example`（含 AdSense + Adsterra 所有 key）
   - `components/Adsterra*.tsx`、`components/AdSenseUnit.tsx`
   - 修改 `app/layout.tsx` 接入广告组件
6. **决策记录**：`{日期}-站点决策记录.md`（每次继续/换站的判断依据）

---

## 执行要点

1. **数据采集优先 7 天窗口，新站额外拉 24 小时窗口**：7 天是"补页面决策"的最佳时间窗口；但新站（上线 < 4 周）长窗口会坍缩到同一份已处理数据，需额外拉「24 小时」近实时窗口看"是否在加速"（见步骤 1.1 新站三窗口 SOP）。短于 7 天噪声大，长于 28 天滞后。
2. **导出 GSC 搜索词用 CSV 按钮**：比逐条复制高效 10 倍。下载后用 pandas 处理。
3. **补页面不要一口气补 10 个**：补 2-3 个观察 1-2 周看收录和排名，再决定是否继续。
4. **AdSense 被拒是常态**：被拒 1-3 次是正常的，每次被拒都按"常见拒审原因"逐项修复再提交。
5. **Adsterra Key 必须用环境变量**：硬编码在代码里不安全（一旦仓库泄漏就被滥用），用 `NEXT_PUBLIC_ADSTERRA_*_KEY` 环境变量传入。
6. **AdSense 与 Adsterra 组合时**：AdSense 放主要位（文章顶部）、Adsterra 放次要位（侧边栏/底部）。单页广告总数不超过 3-4 个。
7. **不要因为前两周没收入就放弃**：新站前两周展示 < 100 几乎是常态，第 3-4 周开始有起色。
8. **决策要记录，不要只记在脑子里**：每次继续/换站的判断都写一行 markdown，下次回看时一目了然。
9. **不强求每个站都成功**：3 个站里 1 个有持续收入就是合理预期。把精力集中在"识别赢家"而非"挽救输家"。

---

## 浏览器抓取要点

1. **统一用 `mcp_playwright-extension`**：GSC、AdSense、Adsterra 后台均通过本地浏览器抓取，**禁止用 WebFetch 替代**（登录态 + JS 渲染拿不到真实数据）
2. **GSC 图表是 SVG**：用 `browser_evaluate` 取 `innerText` 比解析 SVG circle 点位更可靠
3. **导出按钮在右上角**：GSC 性能页右上角"导出" → "下载 CSV"，比逐条复制高效
4. **AdSense 申请页分多步**：用 `browser_snapshot` 拿当前 step 的 ref 再逐步操作
5. **Adsterra 广告代码动态生成**：弹出框出现后**等 2-3 秒**再读代码（否则拿到的是 loading 状态）
6. **等待加载**：每次 `browser_navigate` 后必须 `browser_wait_for`，避免抓到空页面
7. **一个浏览器实例复用**：playwright-extension 共享一个浏览器会话，多个查询顺序执行
8. **GSC 性能页默认 3 个月窗口**：首次进入务必切到 7 天，否则看的是 3 个月汇总的均值
9. **⚠️ 页内 `fetch()` 跨域会报 `Failed to fetch`，这是 CORS 不是站点故障**：在 A 域的页面里 `fetch('https://B域/')` 必然失败，**不能据此判断 B 域挂了**。检测 www 跳转、其他域名可用性，必须用 `browser_navigate` 实测最终落地 URL。同源路径（如 `/about`、`/sitemap.xml`）用 `fetch` 探测状态码则完全可靠
10. **GSC 切日期窗口要用 UI 按钮、不要依赖 URL 参数**：GSC 性能页的日期范围（3 个月 / 7 天 / 24 小时）用 `date_range=` / `num_of_days=` / `num_of_months=` 等 URL 参数切换**不可靠**——默认 3 个月视图会覆盖参数、数据不真正切换（实测三档都显示同一份 3 个月数据）。正确做法：用 `browser_click` 点顶部日期选择器按钮，再 `browser_wait_for` 4–6 秒等卡片重渲。反之，**GA4 的维度切换（explorer 卡片的 `seldim` / `selmet` 参数）用 URL 参数改更稳**（见步骤 5.5.3）。
11. **截图落盘位置**：`browser_take_screenshot` 存到 `.workbuddy/logs/mcp-runtime/custom-mcp_playwright-extension-*/` 下，**必须 `cp` 到项目目录**才能交付给用户

---

## 实战踩坑教训

1. **GSC 性能页默认 3 个月窗口**：首次进入务必切到 7 天，否则看到的指标是 3 个月均值，无法反映当前趋势。

2. **AdSense 申请被拒的常见原因不是内容质量，而是缺基础页面**：「内容太少、内容质量差、缺隐私页」是三大原因，**隐私页和关于页的优先级高于内容质量**。先把这 3 个页面补齐再申请，通过率显著提升。

3. **AdSense 被拒后不要立即重新提交**：每次提交 Google 都视为新申请，连续提交会被判 spam。建议每次被拒后间隔 2-3 周，补 5-10 篇内容 + 修复拒审原因后再提交。

4. **Adsterra 不要选 Popunder**：Popunder（点击背后的弹窗）短期 CPM 高，但严重影响用户体验、易触发广告拦截器、违反 AdSense 政策。新站一律用 Native Banner 或 Banner。

5. **Adsterra 注册必须用顶级域名**：用 Vercel 默认域名（`*.vercel.app`）注册会被拒。**必须先绑定自定义域名**（参考 `yxz-deploy-pipeline` 第三阶段），再用 `https://yourgame.wiki` 形式提交。

6. **AdSense 同一个 Google 账号关联多个域名会被合并审核**：如果你用同一个 Gmail 注册了多个站点的 AdSense，所有站点的审核会**互相影响**——一个站拒审，其他站也跟着延迟。新建账号前考虑站点是否值得投入。

7. **GSC 搜索词报告的展示量门槛**：低于 100 展示的搜索词基本是噪声，不值得专门补页面。**只看展示量 > 100 的搜索词**，能筛掉 80% 的"伪需求"。

8. **平均排名 > 10 的页面几乎没流量**：GSC 显示的"平均排名"是均值，实际分布可能是 30% 在第 1 页 + 70% 在第 5 页以后。**真正有效的指标是排名分布**，不是平均值。

9. **Adsterra 的广告 Key 一旦生成不能修改**：每个 Key 绑定一个广告位（尺寸、格式）。删除广告位后 Key 失效，重新生成会得到新 Key。**代码里 Key 变更需要重新部署**。

10. **新站前两周 GSC 数据几乎全是 0**：Google 索引新站需要 1-2 周，前两周 GSC 看不到任何数据是正常现象。**不要在前两周就放弃**——真正的判断窗口是上线第 3-4 周以后。

11. **GSC "未收录"≠ 缺内容**：GSC 报告"未收录"有多种原因（重复内容、robots.txt 屏蔽、noindex 标签、规范化错误）。**不要直接判定为"内容问题"**，先用 URL 检查工具确认具体原因。

12. **AdSense 与 Adsterra 不可同时显示同一尺寸 Banner**：两者会互相挤占位置，造成广告位空缺。**分开用不同尺寸 / 不同位置**（AdSense 728x90 在文章顶部，Adsterra 468x60 在侧边栏）。

13. **新站接入 AdSense 后前 3 天收入几乎为 0**：Google 需要时间匹配广告主，初期展示的可能是低单价广告。**耐心等 1-2 周**，广告主匹配稳定后单价会显著上升。

14. **Adsterra 后台的 Adult ads 默认开启**：注册时默认勾选，会显示成人/博彩类广告。**务必手动关闭**——既影响用户体验，也可能导致 AdSense 审核连带被拒。

15. **GSC 搜索词报告里有大量"无关词"**：色情、盗版、博彩相关的搜索词经常混入。建议用 `df[df['查询'].str.contains('xxx|adult|casino|free download')]` 过滤后导出。

16. **AdSense 广告代码插入位置影响收入 5-10x**：文章顶部的广告位 CTR 通常比底部高 3-5x。**不要机械地放在所有页面的"页脚上方"**——要根据用户视线动线优化。

17. **Adsterra 注册信息必须真实**：后续收款时需要验证身份（身份证 / 地址证明）。**用真实信息注册**，避免收款时卡 KYC。

18. **新站不要为了通过 AdSense 审核堆砌低质量内容**：堆砌内容短期能通过审核，但 3-6 个月后 Google 算法更新会被降权。**宁可被拒几次，也要保证每个页面都是真实有用的**。

19. **GSC 趋势突然下跌可能是 Google 核心算法更新**：每月中旬 Google 有"Quality Update"，可能导致新站小幅下跌。**不要急着改内容**，观察 2 周再判断。

20. **补页面后立即提交 GSC 请求索引**：新建页面默认等 Google 自然抓取（可能 1-4 周）。**手动提交请求索引**（GSC 顶部搜索框 → 输入 URL → "请求编入索引"）可缩短到 1-3 天。

21. **GSC 的「24 小时」是近实时数据，与长窗口（3 个月 / 7 天）不是同一份**：长窗口是已处理数据（滞后 2–3 天），24h 是当天/昨天的原始数据（滞后数小时）。同一站点 24h 的点击/曝光常远高于长窗口日均——这是长窗口还没处理到最新两天，不是矛盾，也不代表"昨天突然爆了"。决策时把 24h 当作"加速信号"而非"趋势值"，别用 24h 的绝对值去和长窗口日均做除法。

22. **切 GSC 窗口后必须等卡片渲染出数字再读数**：切窗口（尤其 24h）后若立即用 `browser_evaluate` 读 `body.innerText`，页面可能还停在上一窗口的"正在加载…"状态，读到的会是旧窗口/坍缩数据，导致误判（曾误把 24h 读成与长窗口一致的 0/9，直到看截图才发现实为 6 点击 / 179 展示）。正确流程：点按钮 → `browser_wait_for` 4–6 秒 → 确认 4 张卡片显示数字 → 再截图/读数；或直接用截图肉眼读数最稳。

---

## 常见问题排查

| 问题 | 原因 | 解决方案 |
|------|------|----------|
| GSC 数据全部为 0 | 新站上线不足 2 周 / 未提交 sitemap | 等 2 周后重查；确认 sitemap 已提交（参考 `yxz-deploy-pipeline` 第四阶段） |
| GSC 展示量正常但点击量为 0 | 标题/描述不吸引人，或排名在第二页以后 | 优化 meta title/description；提升内容质量争取首页排名 |
| AdSense 申请被拒 | 内容太少 / 缺隐私页 / 缺联系页 | 按"实战踩坑 2"逐项修复，2-3 周后重新提交 |
| AdSense 通过后无广告展示 | GA/AdSense 环境变量未配置到 Vercel | 在 Vercel Project Settings 添加 `NEXT_PUBLIC_ADSENSE_PUB_ID` |
| Adsterra 审核被拒 | 用了 Vercel 默认域名（`*.vercel.app`） | 绑定自定义域名后再注册 |
| Adsterra 收入几乎为 0 | 广告拦截器 / Adult ads 误开 | 检查浏览器扩展、关闭 Adult ads |
| 补页面 2 周后 GSC 仍无展示 | Google 未收录 / 被判定重复内容 | 用 URL 检查工具看具体原因，参考 `yxz-deploy-pipeline` 排查 |
| 搜索词报告全是"无关词"（色情/盗版） | 站点被恶意引流或权重异常 | 暂时不处理，聚焦展示量 > 100 的真实搜索词 |
| AdSense 政策警告（"广告密度过高"） | 单页广告位 > 3 个 | 减到每页 2-3 个广告位，等待 2 周自动解除 |
| 决策摇摆：继续还是换？ | 没建立判断标准 | 用第六阶段模板，每次决策前对照 4 个信号打分 |
| 线上页面突然全部打不开（`ERR_CONNECTION_CLOSED` / SSL 握手失败） | **大概率是本机代理故障，不是站点挂了** | 先按下方「站点不可达分层定位法」排查，别急着回滚部署 |
| 本地 `next build` 通过但线上仍 404 | 改动未 commit / 未 push，Vercel 从 git 构建 | `git push` 触发部署，等 1-2 分钟后再用浏览器复验线上状态码 |

---

### 站点不可达分层定位法（避免误判为部署事故）

> 报「站点打不开」时，**第一反应不应是回滚部署**。国内开发环境下，代理层故障的概率远高于 Vercel 挂站。按下面顺序 5 步即可定位，全程只读不改。

| 步骤 | 动作 | 判读 |
|------|------|------|
| 1 | 访问**竞品站/第三方站**（如 `api.ipify.org`） | 也失败 ⇒ 不是目标站的问题，继续往下 |
| 2 | 对照测**国内站**（`baidu.com`）与**国外站**（`example.com`） | 国内通、国外断 ⇒ 定位到代理层 |
| 3 | `nslookup <域名>` 看解析结果 | 返回 `198.18.x.x`（保留测试网段）= Clash/mihomo **fake-ip** 模式 |
| 4 | **绕过路由直接走代理端口**：`curl -x http://127.0.0.1:<混合端口> <URL>` | 返回 200 ⇒ **站点和代理节点都健康**，故障在 TUN/路由/DNS 层 |
| 5 | `route print -4` 查默认路由 | 存在 TUN 网关（如 `198.18.0.1`，metric 0）⇒ TUN 已接管但 fake-ip 映射对不上 |

**最常见根因**：代理核心重载后 fake-ip 映射表重建，但 OS/浏览器 **DNS 缓存仍持有旧 fake-ip**，核心查不到该 IP 对应域名，只能尝试连字面不可路由 IP → 连接被关闭。

**修复优先级**：
1. `ipconfig /flushdns`（Windows）/ `sudo dscacheutil -flushcache`（macOS）—— 多数情况一条命令解决
2. 仍不行 → 代理客户端里 TUN 模式 off/on
3. 再不行 → 重启代理核心 / 切换节点

**判定站点健康的黄金标准**：只要 `curl -x <代理端口>` 能拿到 200，就说明**线上没问题**，不要动生产代码。

---

## 后续衔接建议

- **继续路径**：用本技能第二阶段方法持续补页面 → 用 `yxz-game-site-template-maker` 把当前站打磨成模板 → 下一个游戏词用模板快速复制。
- **终止路径**：保留当前站的代码、素材、广告配置 → 用 `yxz-hot-word-miner` 选下一个游戏词 → 用模板开新站。
- **数据驱动决策**：建议每 2 周做一次数据复盘（第七阶段），不要凭感觉判断。

---

## 免责声明

本技能输出内容由 AI 辅助生成，仅供参考，不构成专业运营或投资建议。广告接入涉及第三方平台条款，具体审核结果、收入水平依站点质量与流量而定。
