Worldwide and German asset comparison — 2026-08-04

Every asset the account bought on 2026-08-04, ranked on each measure the day can carry, with the sample bar applied to each. Scoped to that one day: lifetime figures pool budget regimes, campaign structures and country mixes that differ, and this account changes all three inside a week. Where a comparison needs more than a day to mean anything, that is said rather than worked around.

The report clock is UTC. Meta stamps its hourly exports in the ad account's own zone, UTC-7, so this day is the account's 17:00–23:59 on 08-03 plus its 00:00–16:59 on 08-04, restitched from two hourly exports. Two things cannot follow the clock and are labelled on their face wherever they appear: per-country cuts, because Meta serves no hour by country grid, and the matched-hours and regime instruments, which key on Meta wall-clock instants by design.

The day: $446.00 across seven objects that took spend, 785 installs (Meta) at $0.568, within-day revenue $588.70 (ROAS 1.32), booked $921.86 (2.07), cohort at 24 hours $783.90 (1.76) at 35% coverage. Payment cut 2026-08-05 10:59 UTC. The standing per-asset block is in asset_performance_report_2026-08-04.md §8 and is not repeated here; this document is the ranking argument built on it.

1The two questions

Delivery is answerable. CPM, CTR, click→install and CPI are single-clock quantities on thousands of impressions and hundreds to thousands of clicks per arm. They need no maturity and no horizon.

Revenue is not, and it fails two gates rather than one. The far gate is sample: across 1,596 installs and 81 payers the coefficient of variation is 7.72, and required sample scales with its square, so resolving a 20% difference needs 23,363 installs per arm. The largest arm on this day carried 221. That is 0.9% of the requirement.

The near gate binds first. No arm on this day reaches the 16-payer bar (#37): pool5 12, bodysuit 11, bikini 8, spill2 4, mugshot 1. There is no per-asset revenue ranking here to defend. Every revenue ordering below is a direction, and the difference between a twelve-payer arm and an eleven-payer arm is not a result at all.

2Delivery

rankassetCPICTRclick→installCPMspend
1spill2$0.36913.34%25.71%12.66$30.27
2bodysuit$0.5137.63%27.56%10.77$113.28
3bikini$0.5409.03%24.79%12.09$111.81
4pool5$0.5628.88%23.56%11.77$103.49
5mugshot$1.03410.43%14.99%16.17$75.48

Three readings, all safe at this sample:

One delivery result clears significance day-over-day, on the ad account's clock. The matched-hours instrument keys on Meta's own delivering hours, so it is reported as the instrument produces it and its day boundaries are not this report's. Held to matched hours at a fixed horizon of six hours, bodysuit's click→install fell 36.33% → 25.55%, −29.7%, p = 0.001, on flat CPI ($0.511 → $0.506). It is the only p < 0.05 negative in the comparison, and it shares its window with bodysuit's own $100 → $150 budget change at 12:31 account time, so the decline and the budget move cannot be separated here. bikini (p = 0.224), pool5 (p = 0.240) and mugshot (p = 0.052) do not separate. spill's +913% (p = 0.000) is the rejected build being replaced by its copy and is already recorded (DECISION_LOG.md #50).

3Revenue

Within-day is sealed and is the only revenue basis used in this table. Spend and the wROAS built on it are the UTC day; the two country columns are a META-day cut and are seven hours offset from everything beside them.

assetwithin-daywROASpayersARPPUlargest payerUS % of spend (META day)US % of its revenue
pool5$228.502.211219.0438.9%13.5%41.1%
bodysuit$177.481.571116.1325.3%13.4%21.4%
bikini$54.670.4986.8323.6%9.2%9.1%
spill2$38.611.2849.6554.2%7.9%0.0%
mugshot$6.320.0816.32100.0%3.2%0.0%

Nothing in this table clears the payer bar. Twelve is the highest count the day produced, against a bar of 16, so the wROAS column carries direction and no magnitude at all.

One person decides the order of the top two arms. A single payer paid $88.95 inside this day. That is 38.9% of everything pool5 earned and 15.1% of the account's entire within-day revenue. Remove him and pool5 goes from 2.21 to 1.35, below bodysuit's untouched 1.57. The ranking between the day's two leading arms turns on one person, and it does so whichever country he sits in.

Where he sits is pool5's United States cell. $14.10 of United States spend on the country cut, 13.5% of pool5's own spend there, returned $93.94 within-day, which is 41.1% of the asset's revenue and 16.0% of the day's. That cell holds exactly two payers, $88.95 and $4.99; the larger is 94.7% of it. The same creative bought $15.17 of India on the same cut and returned within-day 0.76 there.

The mix column separates two arms from the rest, both on the positive side. pool5's United States revenue share is 3.0× its United States spend share and bodysuit's is 1.6×. bikini is level, 9.1% of revenue against 9.2% of spend, and mugshot and spill2 earned nothing in the United States at all. The two sides of that ratio sit on different clocks, so it is a direction on where the money came from rather than a measured gap.

spill2's $38.61 sits on four payers with one of them worth 54.2% of it. Same shape as pool5's cell, a fifth of the money, and further under the bar.

4Holding the budget and the mix constant

This section runs on the ad account's clock. The estimator keys every cell on Meta's delivering hour and its regimes are Meta wall-clock instants: a budget changed at 12:31 on the account's clock, and that is the event. Its window spans the account's 08-03 and 08-04 rather than this UTC day. Cells matured to H=12. mix-neutral re-prices each arm's return on its regime's own pooled country mix, holding its own cost and revenue efficiency. It answers what an asset would have returned buying what its siblings bought.

regimeassetinstallsCPICTRIndia shareROASmix-neutral
E2-R1bikini1600.4368.82%34%1.121.00
E2-R1bodysuit1110.5066.90%17%1.051.08
E2-R1pool51110.6019.93%15%1.000.81
E2-R1mugshot950.8528.64%22%0.210.25
E2-R1spill851.3081.67%7%0.050.07
E2-R2bikini1320.5458.29%40%0.540.63
E2-R2bodysuit1060.5467.02%25%1.121.17
E2-R2pool5810.6688.59%15%3.341.93
E2-R2mugshot500.98110.95%22%0.00
E2-R2spill350.30910.64%23%2.463.81
E2-R3bikini230.38312.43%35%0.960.97
E2-R3bodysuit320.34312.00%12%2.392.06
E2-R3pool5370.23210.60%0%2.161.89
E2-R3spill240.37715.18%12%0.640.98

E2-R1 is the only stretch this account has run with all five arms on the same $100 budget, and it is where the mix confound is cleanest to read. There pool5's raw 1.00 becomes 0.81 once its country mix is neutralised, putting it below bikini at 1.00 and bodysuit at 1.08.

Mix-neutralising moves pool5 down in all three regimes and moves no other arm down by more than 0.33, which is bodysuit in E2-R3 on 32 installs. That is the same conclusion §3 reaches from the payer side, reached independently from the country side.

Two arms rise after neutralising, both on thin cells: spill in E2-R2 (2.46 → 3.81 on 35 installs) and in E2-R3 (0.64 → 0.98 on 24). Neither is separable at those counts.

The UTC day sits across the seam. Its first seven hours fall inside E2-R1 with every arm at $100, the middle runs the whole of E2-R2 with spill at $25 against the rest at $100, and the last four hours open E2-R3 with bodysuit at $150. Seven of twenty-four hours are budget-matched.

5What the day supports

6The German-speaking assets

On this clock the day catches only the buy's first three delivering hours, 21:00 to 23:59, and two of the fifteen creatives sharing its single ad set took any spend inside them. $11.67 spent, five installs at $2.334, $25.41 within-day from one payer.

creativespendimpressionsCPMCTRclick→installinstallsCPIwithin-day
german_mature_10s$9.8820348.675.42%36.36%4$2.470$25.41
latina_true_10s$1.793649.728.33%33.33%1$1.790$0.00

No German asset is decidable, and the gap is not close. The better-looking of the two is one payer, and one creative took 84.7% of the window's spend.

What this window can carry is the price of a German impression. Against the worldwide buy on the same day:

CPMCTRcost per clickclick→installCPI
German-speaking$48.835.86%$0.83435.7%$2.334
Worldwide, five arms$12.209.05%$0.13523.8%$0.566
German multiple4.00×0.65×6.19×1.50×4.12×

Only the first column survives the sample. 239 impressions at four times what the worldwide arms paid is a price, and prices read cleanly on hundreds of impressions. Everything to the right of it rests on 14 clicks and 5 installs: that is why the click→install column reads above the worldwide rate here, which is not a claim anyone should carry out of this table. At this depth the funnel below the impression is a direction and never a rate, and no statement about the landing page, the store listing or the purchase flow can be made from it.

That is a statement about this window, not about the German buy. A lifetime funnel read across the buy's whole life is a different cut on a far larger click sample, and this document does not make it either way. Anything concluded here about what sits above or below the click applies to three hours and fourteen clicks.

The rest of the buy's first day belongs to 08-05 on this clock. Three further German creatives spent on the ad account's 08-04 after 17:00 account time, all of it outside this UTC day; on the META-day country cut turkish_mature alone took $18.69 in Germany, more than every creative in the window above combined, and none of it is visible here.

Two consequences follow, and neither is about picking a German creative:

  1. Fifteen creatives in one ad set is what produced the concentration, and no clock touches it. Swapping creatives inside one set answers whether the geography clears its line and still cannot answer which German asset works. That needs one asset per ad set (#41).
  2. The decidable German question is a delivery question. At four times the impression price, separating two German creatives on revenue is unaffordable at any volume this account buys (#48). Judge them on CPM and cost per click, at one asset per ad set, and never on revenue.

7Caveats

8Reproduce

Run from the repository root with PYTHONIOENCODING=utf-8. The config carries tz: &quot;UTC&quot;.

python -m ad_ops.measures       --config _runs/2026-08-05_0804_settled/run_config.json \
                                --day 2026-08-04 --prev 2026-08-03
python -m ad_ops.report_tables  --config _runs/2026-08-05_0804_settled/run_config.json \
                                --day 2026-08-04 --prev 2026-08-03
python -m ad_ops.cohort_arpu    --config _runs/2026-08-05_0804_settled/run_config.json \
                                --days 2026-08-03,2026-08-04

§2's two-proportion tests and §4's regime table run on the ad account's clock, from the sibling config run_config_meta.json, which differs from the UTC one only in tz:

python -m ad_ops.day_compare    --config _runs/2026-08-05_0804_settled/run_config_meta.json \
                                --today 2026-08-04 --prev 2026-08-03 --h 6
python -m ad_ops.asset_estimator hourly --campaign bailingxia_meituan_ww_cvr_260802 --adset '' \
    --ads ww_bikini_10s,ww_bodysuit_10s,ww_pool5,ww_mugshot,ww_spill,ww_lounge \
    --meta <08-03 hourly> <08-04 hourly> <08-05 hourly> \
    --lum _runs/2026-08-05_0804_settled/lum --fx <fx_rates.json>

A UTC day needs the previous account day's hourly export as well as its own, and measures.py raises by name rather than short-filling if it is missing.

Payer-level concentration inside a single country cell, which the standing block reports per asset but not per cell, was read with a short script over measures.Ctx's own loaders rather than a second instrument: _runs/2026-08-05_0804_settled/utc_2026-08-04/cell_payers.py.

Internal — noindex. Not for distribution outside the team.