Daily campaign report — 2026-08-13, against 2026-08-12

Two ad accounts bought installs of this app on this day and both are ours. The portfolio spent $527.31, 89% of it B1's and 11% the two shared Nomad Node accounts; B1 bought $469.10 and got 538 installs at $0.872, against $532.72 and 522 at $1.021 the day before, and its booked revenue was $1,294.09, down 8.3%, while within-day fell 22.6% to $328.81 on a spend cut of 11.9%. Our records read 0.99 of Meta's booked value on B1's own clock, inside the documented 0.91 to 1.06 band, and one campaign carried B1's whole day again; the definitions are in the appendix.

1Overview

2026-08-122026-08-13change
spend$532.72$469.10−11.9%
impressions47,71451,303+7.5%
CPM$11.16$9.14−18.1%
clicks2,6473,360+26.9%
CTR5.55%6.55%+18.1%
installs (Meta)522538+3.1%
click→install19.72%16.01%−18.8%
CPI$1.021$0.872−14.6%
registrations (ours)677681+0.6%
booked$1,411.20 (2.65)$1,294.09 (2.76)−8.3%
within-day$424.78 (0.80)$328.81 (0.70)−22.6%
cohort @ 24h$619.65 (1.16) at 100%$375.97 (0.80) at 100%−39.3%
within-day payers3536+1

Cohort value — ARPU and ARPPU at d0, d3 and d7

Keyed on the INSTALL day and measured from each user's own install stamp: dN is their first (N+1) x 24 h. ARPU is Adjust's own series, the one the partner's dashboard reports; ARPPU is our payment ledger, because Adjust exposes no cumulative distinct-payer count. A horizon the window has not lived through yet is left empty rather than written as zero.

appARPU (d0)ARPU (d3)ARPU (d7)ARPPU (d0)ARPPU (d3)ARPPU (d7)installs
Vloom$0.6143$0.8226$1.0102$12.25$14.54$17.21937

Account spend split. B1 89% and the shared accounts 11% on 08-13, against 85% and 15% on 08-12; the portfolio spent $527.31 against $624.98.

Campaign spend split. Worldwide 100% on both days, so nothing in sections 3 to 5 carries a mix change between campaigns.

Every delivery price fell and the return per dollar fell with them. More installs for less money, earning less each, is a different audience.

B1 bought attention well and converted it worse. CTR up and click→install down, both at p = 0.000, and section 3's hour-by-hour read agrees.

Within-day fell about twice as fast as spend, on a flat payer count above the 16-payer bar. Revenue per payer went $12.14 to $9.13.

⚠ The instrument gate reads 0.99 on B1's own clock, inside the 0.91 to 1.06 band. The apparent drift was the join rate; see Caveats.

2The two ad accounts, side by side

Both accounts are ours: B1 (1738541847343652), whose campaigns are named bailingxia_, and the two shared Nomad Node accounts (835434076171203 and 3267486106793669), whose campaigns for this app are named 0811_ and 0814_*. Those two accounts also run greenvid and pixvoo for other products and none of that delivery is counted here. Each account's day is struck on its own account clock, and the two clocks are not the same; Caveats carries the offsets and how they were established.

What the columns are. DNU is our own registrations, so the cost beside it is not Meta's CPI below, and the revenue columns are booked.

accountspendshareimpressionsCPMDNUCPIpayerspayer%
B1 (ours)$469.1089%51,303$9.14719$0.65212317.1%
Nomad Node (shared)$58.2111%25,233$2.31278$0.209155.4%
Portfolio$527.31100%76,536$6.89997$0.52913813.8%
accountbookedbROASwithin-daywROAScohort@24hcROASARPUARPPU
B1 (ours)$1,353.442.89$328.810.70$375.970.80$1.882$11.00
Nomad Node (shared)$209.133.59$146.812.52$185.803.19$0.752$13.94
Portfolio$1,562.572.96$475.620.90$561.771.07$1.567$11.32

The shared accounts are 11% of the money and a third of the impressions, so portfolio CPM $6.89 is a blend moving with the mix.

Rank the two on within-day or cohort@24h, never on booked, which counts whoever paid that day and so carries each buy's age.

At 15 payers the shared side's return is a direction, not a magnitude — more per dollar than B1 on both install-day measures.

Everything from section 3 down is B1 alone: the shared accounts' export carries no clicks, leads, country or Ad ID to strike those cuts on.

3B1 hourly, 2026-08-13

B1 only, as is every section below this one. Delivery columns are Meta's instrument on both sides of every ratio. Payer rate, ARPU and ARPPU are ours on both sides. The two install counts are never crossed. ours is our registrations in that hour; cov is that hour's cohort coverage at H=24.

hrspendimprCPMclicksCTRinstclk→iCPIourscovbookedbROASwithinwROASwPaycohortcROAS
0$15.802,0597.671497.24%3020.1%$0.52735100%$69.614.41$51.213.244$51.213.24
1$15.302,0607.431266.12%1814.3%$0.85022100%$153.2610.02$56.943.724$56.943.72
2$18.832,3368.061235.27%1915.4%$0.99127100%$29.261.55$10.750.572$10.750.57
3$23.402,5459.191345.27%1914.2%$1.23224100%$27.801.19$0.000.000$0.000.00
4$17.552,5226.961536.07%2013.1%$0.87831100%$109.896.26$8.940.512$8.940.51
5$18.422,6017.081465.61%2517.1%$0.73728100%$12.350.67$5.060.271$5.060.27
6$17.112,3867.171385.78%1813.0%$0.95120100%$19.991.17$0.000.000$0.000.00
7$21.602,3699.121616.80%1811.2%$1.20029100%$20.070.93$0.000.000$0.000.00
8$19.332,5027.731686.71%2816.7%$0.69041100%$42.102.18$9.320.481$9.320.48
9$20.792,1829.531185.41%2521.2%$0.83230100%$20.931.01$17.150.823$17.150.82
10$20.011,94110.311316.75%2619.8%$0.77034100%$29.561.48$53.812.691$68.993.45
11$20.332,2878.891456.34%2215.2%$0.92424100%$32.771.61$5.760.281$5.760.28
12$30.602,43712.561596.52%2817.6%$1.09333100%$40.751.33$5.170.171$5.170.17
13$21.032,05510.231617.83%2616.1%$0.80932100%$24.121.15$6.300.301$6.300.30
14$18.131,35613.371289.44%2217.2%$0.82426100%$75.044.14$31.071.715$31.071.71
15$20.791,86811.131417.55%2517.7%$0.83228100%$77.763.74$10.970.531$10.970.53
16$23.342,21310.551466.60%2819.2%$0.83438100%$121.055.19$10.650.462$20.700.89
17$26.492,6939.841927.13%2513.0%$1.06034100%$33.261.26$9.110.341$9.110.34
18$21.442,04610.481607.82%3622.5%$0.59641100%$62.452.91$0.000.000$0.000.00
19$17.701,40812.571087.67%2119.4%$0.84324100%$46.522.63$4.990.281$10.880.61
20$13.281,9636.771376.98%1611.7%$0.83029100%$30.792.32$12.330.932$28.372.14
21$20.431,96310.411346.83%139.7%$1.57216100%$101.344.96$4.990.241$4.990.24
22$15.761,8788.391266.71%1713.5%$0.92717100%$66.594.23$9.300.591$9.300.59
23$11.641,6337.13764.65%1317.1%$0.89518100%$46.844.02$4.990.431$4.990.43
all$469.1051,3039.143,3606.55%53816.0%$0.872681100%$1,294.092.76$328.810.7036$375.970.80

⚠ Payer counts per hour run 0 to 5. An hourly ARPPU on one payer is that payer's basket and not a rate. Read the all row for level and the hours for shape.

The cohort column is complete across the whole clock. Every hour reads 100% at H=24 against the 08-16 cut, so nothing in it moves again.

Spend is flat across the clock and the delivery ratios are not. Nothing touched the budget all day; CPI ranges $0.527 to $1.572 underneath it.

2026-08-16T12:23:21.426630 image/svg+xml Matplotlib v3.11.1, https://matplotlib.org/ 0 3 6 9 12 15 18 21 hour (UTC) 0 5 10 15 20 25 30 USD Spend by hour 0 3 6 9 12 15 18 21 hour (UTC) 1400 1600 1800 2000 2200 2400 2600 impressions Impressions and installs by hour impressions installs 15 20 25 30 35 installs (Meta Leads) The day's motion — whole account, 2026-08-13 (UTC)
The day's motion: spend by hour, and impressions against installs
2026-08-16T12:23:21.579687 image/svg+xml Matplotlib v3.11.1, https://matplotlib.org/ 0 4 8 12 16 20 hour (UTC) 5 6 7 8 9 CTR % CTR 0 4 8 12 16 20 hour (UTC) 7 8 9 10 11 12 13 USD per 1,000 impressions CPM 0 4 8 12 16 20 hour (UTC) 10 12 14 16 18 20 22 installs / clicks % Click → install 0 4 8 12 16 20 hour (UTC) 0.6 0.8 1.0 1.2 1.4 1.6 USD Cost per install Delivery by hour — whole account, 2026-08-13 (UTC)
CTR, CPM, click-to-install and CPI by hour, whole account

Against the prior day, hour matched to hour

Hours both days delivered in, on the UTC clock: all 24. Only the shared hours are compared.

Counting which way each shared hour points, which needs no weighting and asks only for a direction:

metrichours 2026-08-13 ran higherhours it ran lowersign test
CPM7 of 2417 of 24p = 0.064
CTR18 of 246 of 24p = 0.023
click→install4 of 2420 of 24p = 0.002
CPI8 of 2416 of 24p = 0.152

CTR and click→install survive the unweighted read, so neither is a mix effect. CPI does not, so the day's cheaper install is one.

2026-08-16T12:23:21.748072 image/svg+xml Matplotlib v3.11.1, https://matplotlib.org/ 0 5 10 15 20 hour (UTC) 5 6 7 8 9 10 CTR % CTR 2026-08-12 2026-08-13 0 5 10 15 20 hour (UTC) 8 10 12 14 16 18 USD per 1,000 impressions CPM 0 5 10 15 20 hour (UTC) 10 15 20 25 30 35 installs / clicks % Click → install 0 5 10 15 20 hour (UTC) 0.6 0.8 1.0 1.2 1.4 1.6 USD Cost per install Delivery by hour — 2026-08-13 against 2026-08-12, shared hours only (UTC)
The same four ratios with the prior day laid over the day, shared hours only
The full hour-by-hour pairing, 2026-08-12 → 2026-08-13

Every shared hour, 2026-08-12 → 2026-08-13. All columns are Meta's instrument on both sides of each ratio. Revenue is deliberately absent: per-hour payer counts run 0 to 5, so an hourly revenue column would be one person's basket read as a rate.

hrimpressionsCPMCTRclick→installCPI
001,025 → 2,05911.91 → 7.676.05% → 7.24%27.4% → 20.1%0.718 → 0.527
011,165 → 2,06010.22 → 7.434.55% → 6.12%18.9% → 14.3%1.191 → 0.850
021,282 → 2,33615.02 → 8.065.62% → 5.27%18.1% → 15.4%1.482 → 0.991
031,397 → 2,54513.01 → 9.195.58% → 5.27%21.8% → 14.2%1.069 → 1.232
041,441 → 2,52213.75 → 6.965.69% → 6.07%29.3% → 13.1%0.825 → 0.878
051,334 → 2,60114.74 → 7.084.95% → 5.61%36.4% → 17.1%0.819 → 0.737
061,375 → 2,38614.34 → 7.176.25% → 5.78%17.4% → 13.0%1.315 → 0.951
071,439 → 2,36913.98 → 9.126.67% → 6.80%22.9% → 11.2%0.915 → 1.200
081,959 → 2,50210.21 → 7.734.44% → 6.71%21.8% → 16.7%1.053 → 0.690
092,390 → 2,18210.13 → 9.534.81% → 5.41%16.5% → 21.2%1.275 → 0.832
102,560 → 1,9419.79 → 10.315.16% → 6.75%16.7% → 19.8%1.140 → 0.770
112,335 → 2,28712.56 → 8.895.05% → 6.34%21.2% → 15.2%1.173 → 0.924
121,900 → 2,43711.86 → 12.565.16% → 6.52%13.3% → 17.6%1.734 → 1.093
132,102 → 2,0559.83 → 10.236.04% → 7.83%22.8% → 16.1%0.712 → 0.809
142,189 → 1,3569.89 → 13.376.26% → 9.44%19.0% → 17.2%0.833 → 0.824
152,858 → 1,8689.74 → 11.135.63% → 7.55%21.1% → 17.7%0.819 → 0.832
163,194 → 2,2138.48 → 10.554.79% → 6.60%15.0% → 19.2%1.177 → 0.834
173,634 → 2,6939.97 → 9.845.09% → 7.13%15.7% → 13.0%1.250 → 1.060
183,406 → 2,04610.65 → 10.484.35% → 7.82%23.0% → 22.5%1.067 → 0.596
192,058 → 1,40811.07 → 12.574.96% → 7.67%23.5% → 19.4%0.950 → 0.843
201,306 → 1,96313.48 → 6.776.05% → 6.98%17.7% → 11.7%1.257 → 0.830
211,127 → 1,96317.71 → 10.419.94% → 6.83%17.0% → 9.7%1.051 → 1.572
221,974 → 1,87810.14 → 8.397.45% → 6.71%15.0% → 13.5%0.910 → 0.927
232,264 → 1,6339.10 → 7.136.67% → 4.65%18.5% → 17.1%0.736 → 0.895

4Country, 2026-08-13

2026-08-23T12:43:21.005238 image/svg+xml Matplotlib v3.11.1, https://matplotlib.org/ IN US ID MX PH GB MY CA TR AR AU FR 0 20 40 60 80 100 120 USD delivery raked onto the report clock against two measured margins; revenue is the report day Spend against within-day revenue by country — 2026-08-13 spend within-day revenue
Spend against within-day revenue, by country
2026-08-23T12:43:21.056791 image/svg+xml Matplotlib v3.11.1, https://matplotlib.org/ −0.04 −0.02 0.00 0.02 0.04 USD per install Cost per install by country — 2026-08-13 (report clock)
Cost per install by country

(i) The portfolio by country, 2026-08-13. On the report clock. Meta serves no hour x country grid, so each country cut is raked from its own Meta day onto UTC; our own columns were already there.

ccspendshareimpressionsCPMregistrations (ours)cost/regwithin-daywROASpayers
IN$127.6927.2%15,623$8.17265$0.482$133.271.0427
US$55.2311.8%1,480$37.3332$1.726$85.941.5617
ID$20.384.3%3,077$6.6274$0.275$14.970.736
MX$19.944.3%2,697$7.3954$0.369$14.820.7410
PH$17.463.7%7,441$2.3568$0.257$5.630.322
GB$13.592.9%600$22.6716$0.849$6.040.448
MY$12.032.6%1,880$6.3925$0.481$3.180.264
CA$11.272.4%442$25.498$1.409$11.100.994
TR$11.182.4%612$18.2923$0.486$5.890.532
AR$10.622.3%970$10.9522$0.483$9.980.943
AU$8.391.8%402$20.855$1.678$0.000.003
FR$6.821.5%326$20.925$1.365$0.000.001

173 further countries are not listed, $154.50 between them (32.9% of this block).

Reconciliation, what is measured and what is fitted. Every per-country cell is an allocation across hours; every total is measured. B1 (UTC-7) $126.41 from Meta 2026-08-12 and $342.69 from Meta 2026-08-13, a measured UTC-day total of $469.10.

Absent from the table above, by name: KBM1, HR1. Their spend is in every day-grain table; only their country split is missing.

(ii) The same cut per account, 2026-08-13.

B1

ccspendshareimpressionsCPMregistrations (ours)cost/regwithin-daywROASpayers
IN$127.6927.2%15,623$8.17217$0.588$91.920.7225
US$55.2311.8%1,480$37.3326$2.124$85.941.5617
ID$20.384.3%3,077$6.6241$0.497$9.980.495
MX$19.944.3%2,697$7.3930$0.665$14.820.748
PH$17.463.7%7,441$2.3557$0.306$5.630.322
GB$13.592.9%600$22.6712$1.132$6.040.448
MY$12.032.6%1,880$6.3920$0.601$3.180.264
CA$11.272.4%442$25.498$1.409$11.100.994
TR$11.182.4%612$18.2917$0.658$5.890.532
AR$10.622.3%970$10.9520$0.531$9.980.943
AU$8.391.8%402$20.853$2.796$0.000.003
FR$6.821.5%326$20.925$1.365$0.000.001

172 further countries are not listed, $154.50 between them (32.9% of this block).

Nomad Node

ccspendshareimpressionsCPMregistrations (ours)cost/regwithin-daywROASpayers
AE$0.000.0%0—1$0.000$0.00—0
AM$0.000.0%0—1$0.000$34.99—1
AR$0.000.0%0—2$0.000$0.00—0
AU$0.000.0%0—2$0.000$0.00—0
BE$0.000.0%0—1$0.000$0.00—0
BG$0.000.0%0—2$0.000$0.00—0
BN$0.000.0%0—1$0.000$0.00—0
BO$0.000.0%0—1$0.000$0.00—0
BR$0.000.0%0—24$0.000$0.00—0
CL$0.000.0%0—3$0.000$5.93—1
CO$0.000.0%0—7$0.000$0.00—0
CR$0.000.0%0—4$0.000$18.04—1

43 further countries are not listed, $0.00 between them (0.0% of this block).

KBM1 — no country block: it delivered nothing on this day, a measured zero.

HR1 — no country block: it delivered nothing on this day, a measured zero.

The prior day, 2026-08-12, the same two tables.

(i) The portfolio by country, 2026-08-12. On the report clock. Meta serves no hour x country grid, so each country cut is raked from its own Meta day onto UTC; our own columns were already there.

ccspendshareimpressionsCPMregistrations (ours)cost/regwithin-daywROASpayers
IN$170.7632.1%21,216$8.05383$0.446$149.710.8824
US$61.8711.6%1,133$54.6042$1.473$97.781.5820
ID$18.183.4%2,246$8.1081$0.225$4.990.273
MX$17.003.2%1,871$9.0855$0.309$23.931.414
GB$15.202.9%369$41.2015$1.014$31.162.055
MY$14.302.7%1,615$8.8542$0.340$13.940.984
PH$13.532.5%4,442$3.0570$0.193$8.980.663
AR$10.552.0%604$17.4823$0.459$12.971.232
TR$10.552.0%374$28.1927$0.391$41.233.913
CA$9.421.8%226$41.657$1.346$35.653.784
AU$8.831.7%191$46.154$2.208$5.610.643
IT$7.491.4%315$23.788$0.937$9.991.333

188 further countries are not listed, $175.03 between them (32.9% of this block).

Reconciliation, what is measured and what is fitted. Every per-country cell is an allocation across hours; every total is measured. B1 (UTC-7) $120.74 from Meta 2026-08-11 and $411.98 from Meta 2026-08-12, a measured UTC-day total of $532.72.

Absent from the table above, by name: KBM1, HR1. Their spend is in every day-grain table; only their country split is missing.

(ii) The same cut per account, 2026-08-12.

B1

ccspendshareimpressionsCPMregistrations (ours)cost/regwithin-daywROASpayers
IN$170.7632.1%21,216$8.05260$0.657$132.430.7821
US$61.8711.6%1,133$54.6028$2.210$89.801.4519
ID$18.183.4%2,246$8.1031$0.587$4.990.273
MX$17.003.2%1,871$9.0825$0.680$0.000.001
GB$15.202.9%369$41.2012$1.267$31.162.055
MY$14.302.7%1,615$8.8529$0.493$8.560.603
PH$13.532.5%4,442$3.0546$0.294$8.980.663
AR$10.552.0%604$17.4818$0.586$12.971.232
TR$10.552.0%374$28.1916$0.659$35.343.352
CA$9.421.8%226$41.655$1.885$35.653.784
AU$8.831.7%191$46.151$8.831$0.000.002
IT$7.491.4%315$23.787$1.071$9.991.333

186 further countries are not listed, $175.03 between them (32.9% of this block).

Nomad Node

ccspendshareimpressionsCPMregistrations (ours)cost/regwithin-daywROASpayers
AE$0.000.0%0—2$0.000$0.00—0
AM$0.000.0%0—1$0.000$0.00—0
AO$0.000.0%0—1$0.000$0.00—0
AR$0.000.0%0—5$0.000$0.00—0
AU$0.000.0%0—3$0.000$5.61—1
BA$0.000.0%0—2$0.000$0.00—0
BD$0.000.0%0—2$0.000$0.00—0
BR$0.000.0%0—33$0.000$10.26—2
CA$0.000.0%0—2$0.000$0.00—0
CL$0.000.0%0—7$0.000$0.00—0
CO$0.000.0%0—13$0.000$0.00—0
CR$0.000.0%0—3$0.000$0.00—0

53 further countries are not listed, $0.00 between them (0.0% of this block).

KBM1 — no country block: it delivered nothing on this day, a measured zero.

HR1 — no country block: it delivered nothing on this day, a measured zero.

5B1 aggregate, both days

B1 only, pooled over the 24 hours both days delivered in, on the UTC clock. Meta's instrument on both sides of every ratio.

spendimpressionsCPMclicksCTRinstallsclick→installCPI
2026-08-12$532.7247,71411.162,6475.55%52219.72%$1.021
2026-08-13$469.1051,3039.143,3606.55%53816.01%$0.872

Pooling across hours is a mix comparison; section 3's pairing is the unweighted read of the same days, and where they disagree the mix moved.

The three measures side by side

measure2026-08-122026-08-13moves after the day closes?
booked$1,411.20 (2.65)$1,294.09 (2.76)settled
within-day$424.78 (0.80)$328.81 (0.70)never
cohort @ 24h$619.65 (1.16) at 100%$375.97 (0.80) at 100%frozen, both days

The mix-neutral account line: CPM $11.16 → $9.14, unchanged at 08-12's campaign mix. One campaign delivered both days, so there is no mix to neutralise.

Booked revenue by the day its payer installed

installed2026-08-122026-08-13
the day itself$424.78 (30.1%)$328.81 (25.4%)
one day earlier$245.41 (17.4%)$207.00 (16.0%)
two days earlier$71.35 (5.1%)$170.61 (13.2%)
three days earlier$84.72 (6.0%)$229.17 (17.7%)
four days earlier$95.07 (6.7%)$15.72 (1.2%)
five days earlier$33.27 (2.4%)$50.14 (3.9%)

The top row of this table is the within-day figure. They are the same number seen twice, which is why the gap between booked and within-day is exactly the inherited cohort and nothing else.

A quarter of 08-13's booked revenue came from people who arrived that day, 25.4% against 30.1% and 49.0% on the two days before.

2026-08-16T12:23:22.005697 image/svg+xml Matplotlib v3.11.1, https://matplotlib.org/ booked within-day cohort @ 24h 0 200 400 600 800 1000 1200 1400 USD 2.65 0.80 1.16 2.76 0.70 0.80 the number above each bar is that measure's ROAS against the same day's spend The three revenue measures, 2026-08-12 against 2026-08-13 (UTC) 2026-08-12 2026-08-13
The three revenue measures on both days, ROAS above each bar
2026-08-16T12:23:22.061093 image/svg+xml Matplotlib v3.11.1, https://matplotlib.org/ 2026-08-12 2026-08-13 0 200 400 600 800 1000 1200 1400 USD the bottom segment IS the within-day figure: the same number seen twice Booked revenue by the day its payer installed (UTC) the day itself one day earlier two days earlier three days earlier four or more
Booked revenue by the day its payer installed

6B1's campaigns, side by side

These are B1's campaigns and no others. Delivery is Meta's instrument on both sides of every ratio; every revenue measure is ours. Cohort horizon H=24h. Report clock UTC. Rank on CPM, cost per click and CPI only — geography is the treatment here, while revenue still needs 16 payers (DECISION_LOG.md #37, #48).

campaignspendshareimpressionsimpr shareCPMclicksCTRcost/clickinstallsCPIwithin-daywROASpayers
Worldwide$469.10100.0%51,303100.0%9.143,3606.55%$0.140538$0.872$328.810.7036

Booking with no delivery, and excluded from every rate above: German (DE/AT) 0 installs (Meta), 0 registrations (ours), $0.00 within-day; Earner (retired 08-03) 0 installs (Meta), 71 registrations (ours), $0.00 within-day. Counting them would put installs into the CPI denominator against spend that never happened.

The retired earner still produces 71 registrations a day on no spend, twelve days after switch-off, down from 95 and earning nothing within-day.

The standing charts for this section plot spend share, CPM and CPI by campaign across the run. One campaign has delivered on every day in the window, so all three would be a single flat line and the chart generator emits none.

7Inside B1's worldwide campaign

Still B1 only, one level further down. Every table and every chart below is that one campaign.

Structure on this day

One ad delivered, alone in its own ad set, for all 24 hours. The ad-set row is therefore the ad row on this day, and the tables below are labelled by asset. That identity is a property of this day's cut rather than of the object model, and it has to be re-checked on any day two ads deliver together.

Six further ads sit in the campaign and none of them delivered. Four carry registrations and booked revenue with no spend, which is the same conversion-hour effect the appendix describes, one level down.

A. Per asset — delivery

Meta's instrument on both sides of every ratio. Our registrations never enter this table.

assetspendimpressionsCPMclicksCTRinstallsclick→installCPI
E2/pool5$469.1051,3039.143,3606.55%52815.71%$0.888
E2/bodysuit$0.000—0—4—$0.000
E2/lounge$0.000—0—4—$0.000
E2/bikini · E2/spill2$0.000—0—1 each—$0.000
earner/bodysuit · earner/bikini · earner/pool5 · E2/mugshot · E2/spill$0.000—0—0——

B. Per asset — the three revenue measures

Ours on every column. Meta can express only booked, so it rides bracketed beside that column and never as a row. Payers are distinct people, never transactions. Cohort horizon H=24h, 100% covered on this day. Report clock UTC.

assetbookedbROAS (Meta)within-daywROAScohort@HcROASpayerspayer%ARPUARPPUlargest payer
E2/pool5$659.681.41 (1.72)$319.510.68$366.670.78346.1%0.5709.4016.8%
E2/bodysuit$223.45—$3.18—$3.18—13.8%0.1223.18100.0%
E2/lounge$152.02—$6.12—$6.12—133.3%2.0406.12100.0%
E2/spill2$132.42—$0.00—$0.00—00.0%0.000——
E2/bikini$61.80—$0.00—$0.00—00.0%0.000——
earner/bodysuit$30.67—$0.00—$0.00—00.0%0.000——
earner/bikini$15.59—$0.00—$0.00—00.0%0.000——
earner/pool5$3.40—$0.00—$0.00—00.0%0.000——

The 16-payer bar (#37): any row above whose payer count is under 16 is a direction and never a magnitude. pool5 clears it with 34. Nothing else on this page does.

pool5's revenue row is the least concentrated this series has produced: largest single payer 16.8%, against 82.6% and bodysuit's 10.9% on 08-12.

C. Per asset — country mix

⚠ This table is cut on the META day, a seven-hour-offset window against tables A and B. Read it for mix, never for level against them.

The last column is the share of that asset's own within-day revenue that came from the United States: where it far exceeds the US spend share, the return is a property of the geography the asset bought.

assetspendIndia %US %other %US % of its revenue
E2/pool5$431.3326.1%12.3%61.6%26.9%

pool5 bought 26.1% India on its full day, 21.8% on its partial day, 36.2% for bodysuit — a gap that has held across every read.

2026-08-16T12:23:22.369626 image/svg+xml Matplotlib v3.11.1, https://matplotlib.org/ E2/pool5 0 20 40 60 80 100 % of that asset's spend Where each asset bought — share of its own spend by region, 2026-08-13 (META day) IN US MX ID PH GB other
Where each asset bought: share of its own spend by region
2026-08-16T12:23:22.416607 image/svg+xml Matplotlib v3.11.1, https://matplotlib.org/ E2/pool5 0.0 0.5 1.0 1.5 2.0 2.5 3.0 3.5 USD per install Cost per install by region — every asset, 2026-08-13 (META day) IN US MX ID PH GB
Cost per install by region, every asset
2026-08-16T12:23:22.462499 image/svg+xml Matplotlib v3.11.1, https://matplotlib.org/ E2/pool5 0 20 40 60 80 USD Within-day revenue by region — every asset, 2026-08-13 (META day) IN US MX ID PH GB
Within-day revenue by region, every asset

The regime read — the comparison this day was waiting for

A regime is a stretch over which the ad set's daily budget did not change. It matters because the budget is a geography dial on this account: raising it buys wider and cheaper countries, so two creatives measured across a budget change are compared on different audiences (DECISION_LOG.md #47).

The campaign's activity history was re-read for 08-11 to 08-14 before this report was written. Its newest row is Aug 12 at 2:18 PM account time, the switch that opened E2-R10. Nothing changed on 08-13 or 08-14, so E2-R10 ran the whole of this report's day untouched.

Cells matured to H=6h, read on the account's own clock, which is where the estimator works. Both regimes are matured against this republication's payment cut, so E2-R10 carries more matured cells than the same regime did when this day first closed — the same cohort read at a later age, not a different one.

adregime$/daymatured installsspendCPMCTRIndia %CPIRPIROAS
bodysuitE2-R9$450545$529.3011.735.45%37%$0.9710.7270.75
pool5E2-R10$450750$598.208.746.33%26%$0.7980.5960.75

A real comparison, and the first this campaign has produced. Same budget, one creative swapped, and neither regime is young enough to be biased.

On cost, pool5 wins for the sixth consecutive read and by the widest margin yet: impressions 25.5% cheaper, installs 17.8% cheaper.

Level on revenue is not a verdict. A coefficient of variation of 6.52 puts separation at 16,692 installs an arm; the larger has 4%.

pool5 holds its cost advantage over a full day. The revenue question cannot be settled at this account's volume, and within-day fell to 0.70.

The day across the run

2026-08-16T12:23:22.546377 image/svg+xml Matplotlib v3.11.1, https://matplotlib.org/ 08-10 08-11 08-12 08-13 day (UTC) 0 1 2 3 4 5 6 7 8 payers / installs % Payer rate by day — every asset (UTC) E2/bodysuit E2/pool5 E2/bikini E2/lounge earner/bodysuit earner/bikini
Payer rate by day, one line per asset
2026-08-16T12:23:22.634537 image/svg+xml Matplotlib v3.11.1, https://matplotlib.org/ 08-10 08-11 08-12 08-13 day (UTC) 0.0 0.2 0.4 0.6 0.8 1.0 1.2 within-day USD per install ARPU by day — every asset (UTC) E2/bodysuit E2/pool5 E2/bikini E2/lounge earner/bodysuit earner/bikini
ARPU by day, one line per asset
2026-08-16T12:23:22.689648 image/svg+xml Matplotlib v3.11.1, https://matplotlib.org/ 08-10 08-11 08-12 08-13 day (UTC) 0 5 10 15 20 25 within-day USD per payer ARPPU by day — every asset (UTC) E2/bodysuit E2/pool5 E2/bikini E2/lounge
ARPPU by day, one line per asset
2026-08-16T12:23:22.741714 image/svg+xml Matplotlib v3.11.1, https://matplotlib.org/ 08-10 08-11 08-12 08-13 day (UTC) 0.4 0.6 0.8 1.0 1.2 1.4 1.6 1.8 revenue / spend Within-day ROAS by day — every asset (UTC) E2/bodysuit E2/pool5 E2/bikini E2/lounge
Within-day ROAS by day, one line per asset
2026-08-16T12:23:22.803689 image/svg+xml Matplotlib v3.11.1, https://matplotlib.org/ CTR click→install CPI payer rate * ARPU * wROAS * 0.0 0.2 0.4 0.6 0.8 1.0 normalised across the day (1.0 = best of the pack) * axis sits under the 16-payer bar on most days: direction only, never a level. Assets under 20 installs on the day are not plotted. Composite — every asset across every measure, 2026-08-13 E2/pool5
Composite: every asset across every measure, normalised across the day

Money-chart markers are hollow where the point sits under 16 payers, and assets under 20 installs on the day are dropped from the composite and the region charts. On this day that leaves one line.

2026-08-16T12:23:22.110178 image/svg+xml Matplotlib v3.11.1, https://matplotlib.org/ 0 2 4 6 8 10 12 14 16 18 20 22 hour (UTC) 5 6 7 8 9 CTR % CTR by hour — every asset, 2026-08-13 (UTC) E2/pool5
CTR by hour, one line per asset
2026-08-16T12:23:22.221267 image/svg+xml Matplotlib v3.11.1, https://matplotlib.org/ 0 2 4 6 8 10 12 14 16 18 20 22 hour (UTC) 10 12 14 16 18 20 22 installs / clicks % Click → install by hour — every asset, 2026-08-13 (UTC) E2/pool5
Click-to-install by hour, one line per asset
2026-08-16T12:23:22.272228 image/svg+xml Matplotlib v3.11.1, https://matplotlib.org/ 0 2 4 6 8 10 12 14 16 18 20 22 hour (UTC) 0.6 0.8 1.0 1.2 1.4 1.6 USD Cost per install by hour — every asset, 2026-08-13 (UTC) E2/pool5
Cost per install by hour, one line per asset
2026-08-16T12:23:22.163216 image/svg+xml Matplotlib v3.11.1, https://matplotlib.org/ 0 2 4 6 8 10 12 14 16 18 20 22 hour (UTC) 7 8 9 10 11 12 13 USD per 1,000 impressions CPM by hour — every asset, 2026-08-13 (UTC) E2/pool5
CPM by hour, one line per asset

8Caveats

⚠⚠ The instrument discarded any payment it could not tie to a person, and this page was republished once that was fixed. measures.py builds its payment list by looking each payment's user up in the registration ledger and skipping what does not resolve, so an unattributable payment was absent from all three measures. Earlier reports in this series stated that such payments were still in booked. They were not.

The payment API leaves the payer field empty on about a quarter of its rows. What it does populate on every row is an account UUID, and the registration feed has been sending that same UUID alongside the numeric user id since the push began at 2026-08-13 18:52 UTC. Nothing on our side was keeping it. Joining the two recovers the payments whose payer registered after that moment, which is why this day recovers a few points and the days after it recover far more:

META daypaymentsresolved beforeresolved afterours ÷ Meta booked, after
2026-08-1220298.0%98.0%1.07
2026-08-1320890.9%93.8%0.99
2026-08-1419770.1%90.4%1.05
2026-08-15234—93.6%1.01

The gate was reading the join rate. This day first published at 0.96, four points under Meta; on the repaired record it is 0.99, so three of those four points were payments the measure was throwing away. Nothing about the account or about Meta's number changed. What is still unrecoverable is payments from people who registered before the push began, because no feed we hold carries their UUID — 69 payments across the whole history, sitting almost entirely in days before this one, which is why the readings before 08-13 do not move under the repair.

Read at one payment cut, on exports since verified to carry all 24 buckets, the series is:

META dayMeta bookedours ÷ Meta
2026-08-08$1,487.111.04
2026-08-09$1,529.211.06
2026-08-10$1,231.391.03
2026-08-11$1,484.951.07
2026-08-12$1,316.961.07 (published as 1.09)
2026-08-13$1,267.000.99

Four of six sit inside the 0.91 to 1.06 band and two sit just outside it at 1.07. A constant systematic offset would not wander in and out. The 1.09 once published for 08-12 was computed against an hourly export pulled at 22:38 on 08-12, account time, while that Meta day was still running: the file held 23 hour buckets, hour 23 absent and hour 22 carrying $9.09 of its final $18.42. A UTC-day report needs only Meta hours 00 to 16:59 of its own day and never touched the missing tail, but the META-clock gate does touch it, and it divided our whole day of payments by Meta's 22 hours. ad_ops/meta_export.py now refuses an hourly export that does not carry all 24 buckets.

What moved on this page. Booked went $1,279.80 to $1,294.09, within-day $314.52 to $328.81 and its return 0.67 to 0.70, the cohort $361.67 to $375.97 at full coverage, the day's payer count 34 to 36, and pool5's payer rate 5.7% to 6.1%. Delivery moved by fifteen cents of spend, eleven impressions and three clicks, which is a second export of a settled Meta day and has nothing to do with the repair.

Cohort at 24 hours now carries the day-over-day comparison, because both days are fully covered. 08-12 and 08-13 are each 100% covered at H=24 against a payment cut of 10:59 UTC on 08-16, so the $619.65 to $375.97 fall is one frozen cohort against another and needs no coverage caveat. The page as first published read this day at 72% coverage and could not make that comparison; within-day, which is sealed at midnight, carried it instead and still agrees with it.

⚠ The 08-12 figures on this page differ from the 08-12 report as published, and the reason is the same short export. That page carried spend $529.61, CPM $11.16 and CPI $1.015; this one carries $532.72 and $1.021. The re-pulled export added $3.11 of spend and 259 impressions spread across all 24 UTC hours, none of it in one place. Within-day did not move at all, at $424.78 on both cuts, which it cannot. The cohort figure is identical to the cent at $619.65 and its coverage rose from 88% to 100%, which is what a fixed horizon is supposed to do.

Payments on this page come from two sources joined. The payment API is the fuller record of what was paid and drops the payer's identity on 18.2% of this day's rows. The Telegram export carries the identity on essentially all of them and stops at 14:50 UTC on 08-13, so from that hour the API is the whole record and the UUID join is what stands between a payment and every measure on this page. This report uses the export as the base and adds the API rows it does not contain, 94 of them on this day. Those 94 are where the UUID join does its work, and where an unjoined row would vanish from all three measures at once.

A whole-day like-for-like is what this day gives and the one before it could not. 08-12 split 21.3 hours of bodysuit against 2.7 of pool5; 08-13 is 24 hours of one asset. Tables A, B and C are therefore whole-day figures for the first time since 08-11, and the hour-of-clock confound that made every per-asset comparison on 08-12 unreadable is gone.

The country section and table C are the account's own day, seven hours offset from every other table. They are read for mix, never for level.

The shared accounts' export runs on a column preset that is not ours, so it carries no clicks, no leads, no country and no Ad ID; the only join key it offers is the ad set name, which measures.py refuses to select on.

The standing chart set has no per-account cut, so section 2 is its two tables and no figures.

The FX table is twelve days old. Revenue in 33 currencies is converted at rates pulled on 2026-08-02, and it prices days through 08-13. With the join rate accounted for it is the only remaining candidate in the open instrument reconciliation, and it has never been tested.

⚠⚠ The two accounts run on different clocks, and each is stitched on its own. B1 is fixed at UTC-7, so its UTC day is built from two account days. The Nomad Node accounts run at UTC+0, so their reporting day is the UTC day and nothing is stitched onto them. Neither offset was assumed: each account's hourly impressions were correlated against our own registrations from its own campaigns, which are true UTC, and the method recovers the known k=7 on B1 at r = 0.878 against 0.703 and 0.698 either side, and returns k=0 on the shared accounts at r = 0.744 against 0.589 and 0.404. Stitching the shared accounts on B1's offset would move their spend seven hours.

Booked cannot rank one account against the other, and booked is the column Meta quotes. It counts everyone who paid inside the day whatever day they installed, so an account carrying three weeks of accumulated cohort and a buy three days old are not being measured on the same thing. Section 2 ranks on within-day and cohort@24h, which count only that day's own installs, and on this day the payer count behind the shared side's figures sits under the 16-payer bar in any case.

Sections 3 to 7 select by Ad ID against the run config's map, so they are B1 alone. The shared accounts' traffic delivers on ad ids ending 334, under campaigns named 0811_vl_bailingxia_srfhjyd-rain-chuva and -health, and those ids were never in that map. No figure in those sections carries their spend or their revenue, and section 2 is where the portfolio is stated.

37% of registrations never enter a revenue measure and that is true of every day in this series. Every "ours" figure means registrations attributable to a mapped Meta ad. It is internally consistent, because the payer rate divides our payers by that same population.

One draft sits unpublished on the account. The manage view reads Review and publish (1). Nothing on this page depends on it and it was not touched.

9What would settle the open questions

Nothing about pool5 against bodysuit on revenue, at this account's volume. The requirement is 16,692 installs an arm and the larger arm reached 750. The two arms are separable on cost and will not become separable on return by running longer at $450 — and on the repaired record they are level on return anyway, which is a statement about the sample and not about the creatives. Deciding between them on revenue needs either a far larger buy or an endpoint with more signal per install than revenue, which is what DECISION_LOG.md #57 proposed in payers per install.

Which instrument the residual gap belongs to. One candidate is left and it has never been tested: the age of the FX table against the days it prices. The candidate that sat on top of it, API payments joining to no user, is the mechanism this page was republished on, and with it removed there is no larger effect hiding the FX question. Repricing one settled day at current rates would answer it in an afternoon.

The 69 payments that still resolve to nobody. They belong to people who registered before the push began at 2026-08-13 18:52 UTC, so no feed we hold carries their UUID and no query will recover them. They are a fixed historical residue. The open question is whether the payment API can populate the user field directly, which would remove the join from the path altogether.

This page was republished on 2026-08-16 after a defect in the payment instrument was found and fixed, and every revenue figure on it moved. The measure discards any payment it cannot tie to a person, and some of this day's payments were arriving identified only by an account UUID that nothing on our side was keeping. The registration feed had been carrying that UUID all along, and joining the two lifts the share of this day's payments that resolves to a payer from 90.9% to 93.8%. This day's within-day revenue moves from $314.52 to $328.81, its return from 0.67 to 0.70, its payer count from 34 to 36, and the instrument gate from 0.96 to 0.99. The delivery half of the report is Meta's instrument on both sides of every ratio and the repair never touched it. Caveats has the measurement and what is still unrecoverable.

This is the first full day of pool5 alone at $450, and it is the day the 08-12 report deferred its revenue read to. The buy ran one creative in one ad set from midnight to midnight with no budget or status change anywhere in the account, confirmed against the campaign's own activity history. Every table on this page is a whole-day like-for-like, which no report since 08-11 has been able to say.

10What this hands to the next read

The 08-14 report inherits E2-R10 in its second full day and a cost advantage that no longer needs establishing. The useful question moves from which creative to what the account does with a buy whose installs are 14.6% cheaper and worth less each. Within-day at 0.70 on a $450 daily is the number to watch, and two consecutive full days of the same regime will be the first pair this campaign has ever offered.

It also inherits a payment record that resolves nearly every row to a payer, and a guard that stops a part-day export reaching a report. The remaining reconciliation is one candidate wide.

11Reproduce

Report clock UTC; B1's exports are stamped in its ad account zone (UTC-7), so every delivery row of its is restitched from two Meta days, while the shared accounts report in UTC and are taken as they come. The country tables and table C are not restitched and are labelled where they appear.

run_runs/2026-08-16_0813_reissue/ (republished; first cut _runs/2026-08-14_2026-08-13_daily_auto/)
payment cut2026-08-16 10:59 UTC, on the repaired join
Meta exportsday and country×day 2026-07-01_2026-08-16 re-pulled 2026-08-16; hourly per day, all 24 buckets verified
registrationsadjust_sink push, pulled 2026-08-13T18:52Z onward, merged onto the Telegram-parsed ledger of 2026-08-14. Carries the account UUID, which is what the payment join needs
paymentsin-app-purchase API, full history, joined onto the export base
FX_runs/2026-08-02_today_read/fx_rates.json
regimescampaign activity history re-read for 2026-08-11_2026-08-15; newest row Aug 12 at 2:18 PM account time
section 2_runs/2026-08-16_receipt_series/, both accounts' hourly exports re-pulled 2026-08-16, payments on the repaired payer join
python -m ad_ops.daily_pipeline --day 2026-08-13
python -m ad_ops.asset_estimator hourly \
    --meta _runs/2026-08-12_0811_daily/exports/ads_hourly_aug11_settled.csv \
           _runs/2026-08-14_2026-08-13_daily_auto/exports/ads_hourly_2026-08-12.csv \
           _runs/2026-08-14_2026-08-13_daily_auto/exports/ads_hourly_2026-08-13.csv \
    --lum _runs/2026-08-16_2026-08-14_daily_auto/lum --fx _runs/2026-08-02_today_read/fx_rates.json \
    --ads "ww_bikini_10s,ww_bodysuit_10s,ww_pool5,ww_mugshot,ww_spill,ww_lounge" \
    --campaign bailingxia_meituan_ww_cvr_260802 --horizon 6
python _runs/2026-08-16_receipt_series/portfolio_split.py \
    --markdown _runs/2026-08-16_receipt_series/blocks

Section 2's two tables are that last command's output for this day, pasted unedited. It stayed a separate reader because the shared accounts' files offer no Ad ID to select on, and --calibrate re-derives each account's offset from data and fails loudly if a stored one stops matching.

The pipeline runs measures, day_compare, cohort_arpu, asset_estimator, report_tables and report_charts in the fixed order, on both the UTC and the META configs it writes, and it now chains the payment and registration ledgers forward from the previous run. The estimator is re-run above across three hourly exports where the pipeline uses two, so that E2-R9 is measured over its whole span.

12Appendix — definitions

The report clock is a UTC day. Adjust reports in UTC, so a UTC-bucketed report lines up with the attribution dashboard without anyone converting in their head. B1 is fixed at UTC-7, so a UTC day on it is account day D−1 17:00 to 23:59 plus account day D 00:00 to 16:59. The two clocks are not close: on a measured day the same figures differed by 14.6% on spend and 40.7% on within-day revenue.

Three things the clock does not reach, each labelled where it appears. Table C's per-asset country mix cannot follow it: the rake is per ACCOUNT, against that account's own hourly margin, and an asset has no hourly margin of its own. The instrument check is invalid off the account's clock, because Meta's conversion value sits on its conversion hour and cannot honestly be restitched. And the estimator runs on Meta's clock deliberately, because its subject is delivery windows and a budget change is an instant on the account's own clock.

The three revenue measures, never one, never mixed, always labelled:

measurecountsmoves after the day closes?
bookedrevenue that arrived inside the day, whatever day its payer installedsettles about four hours after midnight, then fixed. Meta's own number is this basis
within-dayinstalled that day and paid before that day closednever. Sealed at midnight
cohort at Hthat day's installs, counted within H hours of each person's own install. House horizon H=24rises until every install has lived H hours, then frozen. Always state coverage

A day whose spend is falling reads high on booked and low on the other two, purely because yesterday's buyers are still paying. Use within-day for day-over-day, because it is immutable and needs no horizon. Use cohort at a fixed horizon to compare hours to each other, because within-day censors by hour of day. Booked is what Meta will quote at you, so it is reported to explain the gap and never to rank.

All three measures are read on our own payment records, and all three count only payments the record can tie to a person who installed through one of our mapped ads. Meta can express only booked, so it appears bracketed beside that column and never as a row of its own. Quoting Meta's booked against our within-day would mix instruments, and part of the reported gap would be the instrument difference.

Two install counts exist and they are never crossed. Meta's Leads and our own registrations disagree by 5 to 10%. Meta's is used for the delivery funnel, so CPI and click→install have both numerator and denominator on one instrument. Ours is used for payer rate and every revenue measure, so the payers and the installs they came from are the same population.

A regime is a stretch over which the ad set's daily budget did not change. The budget is a geography dial on this account, so two creatives measured across a budget change were compared on different audiences. This day held one throughout: E2-R10, pool5 alone at $450, open since 2026-08-12 14:18 account time.

The 16-payer bar (DECISION_LOG.md #37): below roughly 16 payers a revenue figure is a direction and not a magnitude. Revenue per install on this account is a near-zero vector with rare large entries, with a coefficient of variation near 6.5, so separating two creatives by 20% needs about 16,692 installs per arm. The largest regime-matched arm this account has ever produced is 750.

Internal — noindex. Not for distribution outside the team.