Operations2026.09.05 · 5 min read

App Store Connect の Analytics Reports API で DAU を出したら、同じ日の値が翌日には 2 割増えていた

認証基盤・クラウドインフラ

勤怠アプリの iOS 版の DAU を、App Store Connect の Analytics Reports API から自動で取ろうとした。レポートは TSV で落ちてくるので、Unique Devices を日別に足せば終わりだと思っていた。実際には、同じ日の値が翌日の生成分で 2 割増え、リリース日は端末が二重に数えられ、そもそも解析共有に同意した 42% の端末しか入っていなかった。この 3 つを踏んだ順に書く。

Unique Devices を日別に足せば DAU になる、はずだった

経路はこうなる。認証は ES256 の JWT で、Node の crypto.createSign("SHA256") に dsaEncoding: "ieee-p1363" を渡して署名した(aud は appstoreconnect-v1、有効期限 20 分)。

叩いた順
GET /v1/apps?filter[bundleId]=com.example.app
GET /v1/apps/<appId>/analyticsReportRequests
    # accessType ONGOING の要求が既に 1 件あった。新規 POST は不要
GET /v1/analyticsReportRequests/<reqId>/reports?limit=200
    # 156 本。使ったのは APP_USAGE の 3 本
    #   App Sessions Standard                        r8-<reqId>
    #   App Opt In                                   r189-<reqId>
    #   App Store Installation and Deletion Standard r6-<reqId>
GET /v1/analyticsReports/<reportId>/instances?limit=200
    # granularity DAILY / WEEKLY と processingDate
GET /v1/analyticsReportInstances/<instanceId>/segments
    # attributes.url を fetch → gunzip → ヘッダ行つきの TSV

DAU に使うのは App Sessions Standard で、列はこうなっている。

App Sessions Standard の列
Date  App Name  App Apple Identifier  App Version  Device
Platform Version  Source Type  Page Type  App Download Date
Territory  Sessions  Total Session Duration  Unique Devices

1 行が「その日 × 版 × 端末種 × OS × 流入元 × ページ種別 × ダウンロード日 × 地域」の組で、Unique Devices はその組の中で重複を除いた端末数だ。Date で集約すれば DAU になる。ここまでは正しかった。正しくなかったのは、取れたファイルを 1 本だけ見ていたことだ。

同じ日の DAU が、翌日には 2 割増えていた

DAILY のインスタンスは 2026-09-05 時点で 09-01 から 09-05 の 5 本あり、それぞれ前日までの 5〜6 日ぶんを含み直している(processingDate 09-01 のファイルは 08-27〜08-31、09-05 のファイルは 08-30〜09-04)。同じ Date が最大 5 本のファイルに入っているので、並べてみた。

処理日ごとの、同じ日の合計
# Unique Devices の日別合計
# 左から processingDate 09-01..05

Date 2026-08-30
  8683  9017  9193  9292  9299

Date 2026-08-31
  5677  6812  7107  7233  7303

08-31 の値は、翌日の生成分で 5677 から 6812 に 20% 増え、09-05 の生成分で 7303 まで増えた。初出の値は確定値の 78% だ(09-01 も 5262 から 6590 で 80%)。08-30 は 09-01 のファイルで見えた時点ですでに処理日から 2 日たっていたのに、そこからまだ 7% 増えている。3〜4 日でほぼ止まる。

1 本のファイルだけ見ていると、この遅着には気づけない。値は毎回きれいに埋まっていて、欠けている印がどこにも無いからだ。取り込みは「日付ごとに、一番新しい processingDate のファイルの値で上書きする」形にし、初出の日は暫定と印を付けた。

リリース日は、更新した端末が旧版と新版の両方に数えられる

並べた中で 08-30 だけが 9299 と突出していた。この日は 2.1.0 の配信日で、行は App Version で分かれているので、版別に足し直した。

2026-08-30 の版別 Unique Devices
# Date 2026-08-30 (2.1.0 の配信日)
# App Version 別 Unique Devices 合計

1.0.0      92
1.1.0      54
1.2.0    1258
2.0.1    4069
2.1.0    3826
-------------
合計     9299

# 同日の Installation and Deletion
Manual update   14427

2.0.1 が 4069、2.1.0 が 3826。同じ端末がその日にアプリを更新すると、旧版の行と新版の行の両方に Unique Devices 1 として出る。行を足した 9299 は端末数ではなく、端末と版の組の数だ。同じ日の Installation and Deletion では Download Type が Manual update の Counts が 14427 あった。

最初に考えたのは「合計 − Manual update」を DAU の床にする案で、これは捨てた。08-30 は 9299 − 14427 = −5128、前日の 08-29 も 6390 − 7027 = −637 と負になる。更新しても当日は開かない端末が多く、Manual update は二重計上の上限にすらならない。

採ったのは、Manual update が少ない日を「素の DAU」として読むことだ。09-02 は 1671 件、09-03 は 878 件で、この日の合計 6127 と 5615 はほぼ端末数と見てよい。二重計上は最大でも旧版と新版の少ないほうの行合計だが、日次のレポートからそれを完全に除く手はない。

セッションの数字は、解析共有に同意した 42% の端末ぶんしかない

もう 1 本、App Opt In というレポートがある。列は Downloading Users と Users Opting-In の 2 つで、08-29 から 09-04 の 7 日ぶんを足すと 7196 に対して 3037、42.2% だった。App Sessions の Unique Devices も、Installation and Deletion の Counts も、母集団はこの後者だ。DAU の実数は opt-in の値を 0.42 で割って見積もるしかなく、5,000〜6,100 の日で 1.2〜1.5 万ということになる。

ただし、リテンションならこの係数は消せる。App Sessions には App Download Date 列があるので、端末をダウンロード日ごとに分け、その日の First-time download(Installation and Deletion、こちらも opt-in 母集団)で割る。分子も分母も同じ 42% の中の数なので、比は全体の比と同じになる。

ダウンロード日 2026-08-27 のコホート
# App Download Date 2026-08-27 の端末
# First-time download 1259 で割る

08-27  1035  82%
08-28   536  43%
08-29   379  30%
08-30   445  35%
08-31   354  28%
09-01   290  23%
09-02   253  20%
09-03   235  19%
09-04   231  18%

この端末群では D1 が 43%、D3 が 35%、D7 が 19%。ダウンロード日の違う 08-30、08-31、09-01 のコホートでも D1 はすべて 43% に落ちた。D0 が 100% にならないのは、ダウンロード当日に開かない端末とタイムゾーンのずれだと見ている。

母集団が欠けている数字でも、分子と分母を同じ母集団から取れば比は使える。実数が欲しいのか比が欲しいのかで、同じレポートの使い道が変わる。

まとめ

レポートの 1 行には「何を数えたか」のほかに、「いつ処理された値か」と「誰の集合か」が付いている。Unique Devices は端末ではなく端末と版の組を数え、processingDate が違えば同じ日の値が変わり、母集団は同意した 42% だった。3 つとも列名からは読めず、処理日の違うファイルを並べ、版で割り、別のレポートと突き合わせて初めて分かった。

API から数字を自動で取るときは、最初の 1 本を取り込む前に、同じ値が別の日にどう変わるかを一度見ておく。取れたファイルは毎回それらしく埋まっているので、1 本だけ見ている限り、そこに前提があることには気づけない。

App Store ConnectAnalytics Reports APIiOSDAU