乐于分享
好东西不私藏

用 API 量化独立开发 App 的 ASO 效果

用 API 量化独立开发 App 的 ASO 效果

开头

我个人发布了两款 iOS / Android 应用。一个是「ClassicTimer」,拨盘式厨房计时器;另一个是「かえたお」,用来管理毛巾更换。

应用上线几周后,我最在意的事情变成了:它们真的被用户看到了吗?在浏览器里看 App Store Connect(下文简称 ASC)和 Google Play Console 的管理后台,数字当然能看到。但要追踪“昨天和今天哪里不一样”“那次 ASO 调整到底有没有效果”,就很费劲。

于是我自己做了一个很朴素的分析系统:每天调用两个商店的 API,然后吐出一份 Markdown 报告。结果是,我可以定量比较 ASO 改动前后的表现。比如刷新关键词和分类之后,搜索展示量增长了一个数量级,但 PV 率和点击率反而下降了。数字把下一步该做什么也指了出来。

本文里出现的所有数字都是虚构示例值。它们反映的是实际趋势,但不是具体业绩数据。阅读时可以重点看方法和解读方式。

为什么只看管理后台还不够

ASC 和 Play Console 都有自己的界面,也算好看。但从独立开发者视角用起来,很快会碰到这些限制:

  1. 过去的记录留不住。今天的数字能看到,但如果要和两周前放在一起比,每次都得手动导出。
  2. 很难横向比较。iOS、Android,还有多个 App 的数据,想放到一张表里看并不轻松。
  3. 很难自动处理。比如“这一天更新了元数据,前后 7 天的 impression / tap / DL 发生了什么变化”,只靠后台界面回答这个问题,基本是苦差事。

如果这些东西都能“每天生成 Markdown,然后 commit 到 git”,那就可以用 git diff 直接看差异。这就是我一开始的动机。

整体架构

我面对的是 4 个数据源。

数据源
获取方式
主要指标
ASC Sales Reports
/v1/salesReports
下载量、销售额
ASC Analytics Reports
/v1/analyticsReportRequests
Impression / Page view / Tap、按来源和地区拆分
Google Play Console
通过 GCS bucket 读取 CSV
安装 / 卸载 / 商店访问者 / 获取量
Apple Search Ads Basic
从管理后台手动导出 CSV
广告带来的安装数、支出

它们各自都有坑,下面按顺序说。

ASC Sales Reports:3 天延迟和 1F / 7F

调用 /v1/salesReports,并设置 reportType=SALES,会返回一份日粒度的 gzip TSV。对免费 App 来说,Product Type Identifier 有下面两个含义:

  • 1F:免费 App 的新下载
  • 7F:App 内更新

很容易忽略的一点是,它基本有 3 天延迟。用今天的日期去请求会得到 404。所以我在工具里把默认目标日期设成 today - 3,如果这样还是 404,就平稳跳过。

ASC Analytics Reports:ONGOING 请求方式的坑

Apple 的 Analytics Reports 不是想拿就能直接拿。它需要走 3 步:

  1. 用 POST /v1/analyticsReportRequests 创建一个 accessType: ONGOING 的请求。每个 App 只需要创建一次。
  2. 最多等待 48 小时,让各种报表实例生成出来。
  3. 拿到请求 ID 后,以后每天都用同一个 ID 下载报表。

这个请求 ID 会一直用下去,所以必须存进配置里。

apps:
-name:ClassicTimer
platforms:
ios:
apple_id:"6760642418"
analytics_request_id:"xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx"

报表种类很多,但如果要做 ASO 改善前后的对比,最先用到的是 App Store Discovery and Engagement Standard。它在一份报表里按天、来源、地区给出 Impression / Page view / Tap,做汇总也足够完整。

Google Play Console:通过 GCS bucket 读取,以及 UTF-16 的坑

Google 这边会把 Play Console 的统计报表自动导出到 GCS bucket,名字类似 pubsite_prod_XXXXXX。准备好服务账号之后,就可以用 google-cloud-storage 客户端直接读取。

我踩到的一个小坑是,部分 CSV 会以 UTF-16 返回。直接按 utf-8 打开就会乱码。

import csv
from io import StringIO

raw = blob.download_as_bytes()

# 有 UTF-16 BOM 就按 UTF-16,没有就按 UTF-8
if raw.startswith(b"\xff\xfe"or raw.startswith(b"\xfe\xff"):
    text = raw.decode("utf-16")
else:
    text = raw.decode("utf-8")

reader = csv.DictReader(StringIO(text))

不同种类报表的路径规则,比如 stats/installs/stats/store_performance/,不读文档也不容易猜出来。不过一旦整理好,后面就能稳定跑。

Apple Search Ads Basic:没有 API,只能手动导出 CSV

这里最难受。

Apple Search Ads Basic 没有 API。CSV 可以导出,但文件里只有整个期间的合计。它不能拆成每天的数据,所以“按天减掉广告安装量,算纯自然量”这种本来很自然的处理就做不了。

没办法,我只能先按整个期间评估,再按期间内天数做比例分摊。这是很勉强的做法。Apple Search Ads Advanced 好像有 API,但对 Basic 用户来说,那是另一个世界。

# evaluate_organic.py 的分摊逻辑节选
ads_pre_installs  = round(total_installs * pre_days / total_days)
ads_post_installs = total_installs - ads_pre_installs

只要还在用 Basic 投放,就没办法真正按天分离自然下载量。这是独立开发者搭建 ASO 分析系统时,一开始就应该接受的限制。

日报长什么样

所有数据都会汇总输出到 reports/YYYY-MM-DD.md。大概长这样。数值是虚构示例值。

# App Analytics Report - 2026-04-17

### ClassicTimer (iOS)

#### Sales Reports
下载: **3**

#### Analytics Reports
展示量: **1,150**
产品页浏览: **5**
按来源展示量: App Store search: 1150
按地区展示量: JP: 520, KR: 430, TW: 50, HK: 48, US: 15

### ClassicTimer (Android)(数据: 2026-04-15)
每日安装: **1**
活跃安装: **42**
商店访问者: **8**
商店获取量: **1**

ASC Analytics 有 3 天延迟,Play Console 有 2 天延迟。两边延迟不一样,所以我会在报告里写清楚“数据日期”。比如文件名是 2026-04-17.md,但 Android 这边其实是 4 月 15 日的数据。

之后把这些报告加进 Git,就能留下差异历史。用 git log -p 看“和两周前相比怎么样”,意外地很舒服,有点像在看 ASO 改善 PR 下面的评审意见。

ASO 改善实验

2026 年 4 月 8 日,我一次性修改了 ClassicTimer 的元数据。

分类修改

  • 修改前:Utilities
  • 修改后:Food & Drink

我的假设是,“拨盘式”更多是在厨房计时器这个场景里被使用。Utilities 里各种 App 太多,靠分类被发现的机会也比较低。

关键词刷新

Fastlane 的 metadata/ja/keywords.txt 原本是“用泛化名词去覆盖更多搜索”,我把它改成了“用用途词和特征词命中更具体的需求”。

  • 修改前类似 タイマー,キッチンタイマー,料理,ダイヤル,クラシック,キッチン,...,以泛化名词罗列为主。
  • 修改后类似 ダイヤルタイマー,ゼンマイタイマー,料理タイマー,クッキングタイマー,ポモドーロ,...,优先使用“用途 × 特征”的复合词。

关键词有 100 字符限制,所以要挑那些看起来有搜索量,同时头部竞品又没有强到完全打不过的用途词。英语和韩语 locale 也按同样思路刷新。

副标题修改

我把“クラシックなダイヤル式タイマー”这类特征名词堆叠,改成了“回すだけ。ゼンマイ式の心地よいタイマー”这种体验表达。前者说的是“它是什么”,后者说的是“它用起来有什么感觉”。

Fastlane 联动的运用

元数据散落在各个 App 仓库里,所以我写了一个简单脚本,以中央的 aso.yaml 为准,再推送到各处。

python3 src/update_metadata.py classictimer --dry-run  # 确认差异
python3 src/update_metadata.py classictimer            # 写入 + 执行 upload_metadata

只要改一个中央文件,就能一路跑到 Fastlane 元数据和 upload_metadata。关键词历史也能在同一份 git log 里追,这一点很舒服。

怎么读结果

我用分析脚本 analyze_aso.py 计算了改善前后的日均值。下面这张表是虚构示例值,模拟的是实际趋势。变化率本身的精度不重要,重点看“展示量上了一个数量级,但比例下降”这个形状。

指标(示例值)
改善前(日均)
改善后(日均)
变化
展示量
50
1,000
+1,900%
页面浏览
0.5
4.0
+700%
Tap
0.7
5.0
+614%
下载
0.5
2.0
+300%
PV 率(PV / Imp)
1.00%
0.40%
-60%
Tap 率(Tap / Imp)
1.40%
0.50%
-64%

这些数字可以这样读:

  • 展示量爆了。分类和关键词刷新之后,进入搜索结果的母数增加了一个数量级。
  • PV 率和 Tap 率下降了。新关键词确实让它被搜到了,但用户没有从搜索结果页点进详情页。
  • 下载量增长了,但没有像展示量那样增长。母数变大,同时 CVR 下降,最后大概稳定在 4 倍。

从这里能看出的下一步很明确:胜负会在“搜索结果里的第一张截图”和“图标”上决定。关键词能带来曝光,但如果第一张图不能让人觉得“这就是我想要的东西”,PV 率就回不来。

这个结论,光在管理后台里模模糊糊看数字肯定说不出来。正因为我看到了 PV 率的变化,才判断下一步应该改截图。

区分自然量和广告量

我还用 Apple Search Ads Basic 试着投过一点广告,所以也需要评估纯自然量。

python3 src/evaluate_organic.py report_pre.csv report_post.csv

里面的逻辑就是简单相减。

自然下载量 = ASC 总下载量 - Apple Ads 广告下载量
自然占比 = 自然下载量 / ASC 总下载量

Basic 拿不到按天数据,所以只能把期间合计按天数分摊。结果大概是这样。这里也是虚构示例值。

期间(示例值)
广告占比
自然占比
改善前
45%
55%
改善后
15%
85%

也就是说,ASO 改善之后,它已经更接近“停掉广告也能靠自然量维持下载”的状态。如果不做这个拆分,就会变成“这个月下载涨了,但不知道是因为广告加大了,还是 ASO 起作用了”。

踩坑总结

踩坑点
处理方式
ASC Analytics 的 ONGOING 请求第一次要等 48 小时
一开始就创建并放着等。把请求 ID 存进 apps.yaml,长期复用
ASC Sales Reports 基本有 3 天延迟
默认目标日设成 today - 3,404 就平稳跳过
Play Console 的 CSV 有时是 UTF-16
看 BOM 切换解码器
Apple Ads Basic 没有 API
手动导出 CSV,用期间合计按天数分摊来妥协
Fastlane 元数据散落在各个 App 仓库
用中央 aso.yaml 写入各仓库,再自动执行 upload_metadata
iOS / Android 延迟天数不同
在报告里写清楚“数据日期”

总结

  • 个人开发也值得自己调用 API,搭一个分析系统。相比盯着管理后台里的数字看,用 git diff 看时间线,判断会快很多。
  • ASC Analytics、ASC Sales、Play Console(GCS)、Apple Ads Basic 这 4 条路径各有各的坑,第一次整理会有点磨人。
  • ASO 改善的效果很容易表现成两段:展示量上升,但 PV 率和 Tap 率下降。下一步要改的是截图和图标。
  • 如果没有区分自然量和广告量,就没法判断改善到底有没有生效。

盯着管理后台看,然后隐约觉得“好像有点火了”,和用数字比较前后变化,然后知道下一步该做什么,是完全不同的体验。独立开发者本来就缺判断材料,所以给自己做一块仪表盘,这个投入带来的回报比我想象中大。

两款 App 现在都已经公开。如果你愿意,也可以在真机上看一眼。

来源

原文标题:個人開発アプリの ASO 効果を API で定量化する

作者:Naaw

发布平台:Zenn

发布时间:2026-04-20 22:44:33 JST

原文链接:https://zenn.dev/nawa_10half/articles/solo-dev-aso-analytics-api

相关链接

ClassicTimer: https://10half.jp/classictimer.html

かえたお: https://10half.jp/kaetao.html

推荐阅读:

看懂LLM:从文本到 AI 助手