Why is my app CPI rising or ROAS stalling? Find what changed first.

I am Samet Durgun, a fractional Head of UA. I run paid UA for subscription apps and mobile games and write up what I find in the accounts I manage. This piece sits under what signal engineering fixes; more about me.

When a client tells me CPI went up, I do not start with the auction report. I open the change log. A CPI rise or a ROAS stall can start in the product, in the measurement stack or in the age of the cohorts, and the auction is easy to blame because it is the part of the system that comes with a chart.

Two identities carry the whole diagnosis. CPI is CPM divided by installs per thousand impressions. ROAS at any age is value per install at that age divided by CPI. Everything that moves either number is one of their terms, or a change in how a term is measured, and the job is to find which term moved first. The cases below are from my own accounts and are already published, one account each. Every number in the worked examples is a labeled illustration, and every other figure carries its source.

What changed in the last two to three weeks?

Before any metric, I write down every change from the last two to three weeks, from everyone who can touch the system. App releases and SDK updates. Paywall, price, trial length and onboarding tests. Store page, screenshots, rating. Events, event mapping, the conversion value schema, the attribution windows of the mobile measurement partner (MMP), the ad platform’s attribution setting, a new connector in the BI. Bids, budgets, optimization events, new campaigns, consolidations. New creatives, and the date the last new concept launched. Then I lay the metric break next to that list.

Two of my own cases show where the cause can sit. In a casual game, a store featuring by week 6 took CPI from between £4 and £6 to £10 and order value from £10 to £29, and D0 ROAS came out above 20% both times, through a completely different user profile. Without the featuring in the log, the CPI jump looks like an auction problem. In a fitness app the cost per trial would not go below $30 against a $15 target, and the cause sat in the product, not in the account. The product converted one audience and churned the other, and the audience it converted was too small for Meta to find at scale.

One mechanism makes the log matter more than it looks. If the optimization event is trial start or purchase, a product change that lowers that rate also lowers the signal the platform learns from. Meta, TikTok and Google all weigh predicted action rates in the auction, so a week or two after a product regression the effective price of an impression can rise too. A product problem turns into an apparent auction problem on a delay, and the auction report shows you the second event, not the first.

Which of the three CPI inputs moved?

CPI = CPM ÷ IPM, and IPM, installs per thousand impressions, is 1,000 × click rate (CTR) × click to install rate. Three inputs, and a 30% rise in CPI can come entirely from one of them while the other two sit still. Find the mover before naming a cause.

An illustration, two weeks of one campaign:

Input Week A Week B Moved
CPM $10.00 $11.00 up 10%
Click rate 1.00% 0.80% down 20%
Click to install 30% 30% flat
IPM 3.0 2.4 down 20%
CPI $3.33 $4.58 up 38%

Most of the CPI rise is the click rate. If you want shares, take the log of each ratio. The CPM change explains about 30% of the CPI change and the click rate about 70%. The store did nothing. So the first place to look is the creative and the placement mix, the auction is the second place, and the CPM chart alone would have pointed the other way.

From the table above, shares of the log change in CPI. A full bar is the whole rise.

Each input has its own list of causes.

CPM up, click rate and click to install rate flat. Competition, season, a shift of spend toward more expensive countries or placements, or a lower predicted action rate after an event or audience change. Every documented auction combines a bid with a prediction of response. Meta’s help page names the bid, the estimated action rates and ad quality as the parts of the total value that wins. TikTok says its auction ranks ads on bid price and relevance. Apple Ads says bids are combined with relevance, other advertisers’ bids, reserve prices and the overall user experience on second price principles. So CPM is partly an output of your own creative and signal quality, and a CPM rise is not proof that the market moved. Split CPM by country and placement, and check the same calendar weeks of the previous year before calling it season.

Click rate or IPM down. Creative wearout, also called creative fatigue, is the usual suspect and the least often checked. The symptom I can observe is a specific creative’s IPM falling as its frequency rises, with CPM steady, and spend concentrating on fewer ads. The causes people name, such as a saturated audience or the algorithm punishing them, are usually guesses. The best causal evidence I know says wearout is not one curve, though it is display advertising from 2010. In Lewis’s 30 natural experiments on the Yahoo front page, covering 2.8 billion impressions, four campaigns wore out after one or two exposures, ten showed little wearout after fifty exposures, and naive observational estimates overstated wearout for 26 of the 30. Meta’s own analytics team disagrees in emphasis. In a 2023 post it fits click likelihood falling roughly as (N+1) to the power of minus 0.43, where N is the number of earlier views of the same creative. It puts conversion likelihood about 45% lower at four earlier views. It finds no “wear in” period on direct response, where each repeat only costs more. That is Meta’s observational regression on its own data with no sample stated, and I read it as a shape and not a number. Its split test, adding new creative to fatigued ad sets across roughly 26,000 cases, did improve conversion in proportion to the fatigue. So I test the outcome and leave the cause open. In one tROAS campaign the algorithm kept scaling five ads that never reached the 30% D0 target. I duplicated the campaign without them and ran both for 30 days. In the original, none of the top five by spend hit target. In the copy, four of five did, and the algorithm surfaced six new creatives above target. IPM alone does not tell you which creative to make next, but it does tell you which one stopped working.

Click to install down. The ad still gets the click and the store page loses it. A screenshot change, a rating drop, a price now shown on the page, a featuring that ended, or a mismatch between what the ad promised and what the page shows. Apple’s product page optimization lets you test up to three treatments against the original for up to 90 days, and Apple’s own tech talk on it walks through two tests where the expected winner lost. A screenshot set themed for the holidays lost to the evergreen control, and in another test a screenshot beat the app preview it replaced. A store page change moves CPI with no auction involved, and it is in the change log if anyone wrote it down.

One measurement caveat on the split itself. Installs credited to a view have no click, so installs divided by clicks overstates the conversion rate. Use IPM from one source instead of click rate times conversion from two sources, and expect the platform’s and the MMP’s version to differ. AppsFlyer says that the eCPI Meta calculates and the one AppsFlyer calculates usually differ, because Meta supplies the cost and AppsFlyer counts the installs under its own rules.

Can ROAS fall while CPI stays flat?

Yes. ROAS at age t is value per install at t divided by CPI. For a subscription app, value per install is roughly install to trial × trial to paid × proceeds per first payment × (1 + renewals realized by t). For a game it is payer rate × value per payer + ad revenue per install. Every term except CPI sits downstream of the ad, and the age t is a term of its own.

The game case again, because it is the cleanest I have. Over four weeks the order value fell from £29 to £25 to £23 to £18 on the same campaign, the same setup and the same optimization objective, and D0 ROAS halved from 22% to 11% while CPI barely moved. The whole game was softening. ARPDAU was down 30%, purchase revenue per user down 33% and ad revenue per user down 25%. The revenue mix had gone from 85% purchases to an even split with ads, so order value now depended on ad eCPMs too. That made it more than an acquisition problem. The number that held was cost per purchase, under £30 in every week D0 cleared 20%.

An illustration for a subscription app. CPI holds at $2.00, install to trial holds at 10%, and after a paywall redesign trial to paid falls from 40% to 30% on a $40 first payment. D30 value per install falls from $1.60 to $1.20 and D30 ROAS from 80% to 60%, with the auction, the creative and the targeting untouched. The reverse happens too. Move spend toward countries where an install is worth more and CPI rises from $2.00 to $2.50 while value per install rises from $1.60 to $2.40, so ROAS goes from 80% to 96%. Cut the expensive campaign on CPI alone and you cut the better one. I think of ROAS as intent times fit times funnel strength, divided by cost, and CPI is only the denominator.

Is it the measurement and not the performance?

Several things change the reported number with no change in users, and I rule them out before I touch anything.

Attribution windows. Meta’s Ads Insights API stopped returning the 7 day view and 28 day view windows on 12 January 2026, as Meta told developers in October 2025 and Supermetrics documented for its connector. Any report that still asked for them showed a drop in conversions that was a reporting change, not a performance change. I did not see it in my own accounts, so this is a sourced check and not an observation. The MMP and the platform also differ by design. AppsFlyer lists 7 day click and 1 day view as Meta’s maximum and default, and in one account I measured, campaigns on 1 day view ran about 20% ahead of the MMP on installs. A stable gap is a calibration factor. A gap that moved on a specific date is a settings change.

SKAN and AdAttributionKit. Under SKAN 4 a campaign gets three postbacks, days 0 to 2, 3 to 7 and 8 to 35, with the fine value only in the first. AdAttributionKit, from iOS 18.4, lets each network configure its own windows, so check the durations in your own setup instead of assuming these. Apple’s documentation says the conversion value is conditional and only included when crowd anonymity thresholds are met. Lower volume can drop a campaign a tier and turn its values null, so iOS ROAS collapses on the dashboard while the revenue in RevenueCat is unchanged. A schema or window edit does the same. I wrote up how the trial payment lands in those windows and why Google Ads, the MMP and SKAN disagree.

Event mapping, currency and duplicates. A purchase sent without a value. Revenue in local currency labeled as dollars. Trial and paid events swapped. Refunds or renewals not sent. Test events in production. Two pipelines sending the same purchase, which matters because AppsFlyer notes that Meta deduplicates installs across MMPs but not in app events. And a BI layer that quietly switched from gross to proceeds. I line up SDK release dates with the metric break, and I run the three comparisons between the platform, the MMP and RevenueCat before I believe a drop.

Are the new cohorts just young?

Scaling lowers blended ROAS by itself. Take an illustrative cumulative ROAS curve by cohort age of 10% in week 0, 25% in week 1, then 33%, 38%, 42% and 45% by week 5. Spend $10,000 a week for six weeks and the blended ROAS of everything to date is 32.2%. Keep the four oldest weeks at $10,000 and double the two newest to $20,000, with identical cohort quality, and blended ROAS to date is 28.5%. The account got no worse. It got younger. A budget cut would mechanically recover the blended number, which is the trap.

The fix is the rule from the cohort article. Compare at the same age, D7 against D7 and D28 against D28, by install week. The real question after you scale spend is whether the marginal cohorts are worse than the earlier ones at the same age, since diminishing returns are real, and that question cannot be read off a blended number at all. For the early read I use D0, because in my $606K study D0 ranked 38 campaigns almost the same way D28 did.

Did the account change shape?

Country and placement mix. A blended CPI can rise with every country’s CPI unchanged, because spend moved between countries. Split the change into the part that happens inside each country and the part that comes from the mix, and do the same for placements, since cheap impressions with low IPM lower CPM and raise CPI at the same time. In my country audit one country ran at 28% ROAS for three months inside a campaign that printed 70%, and the blended number never blinked.

Learning resets. Switching the optimization event, the bid strategy or the structure restarts learning and changes which users the platform buys. TikTok tells advertisers not to adjust a bid by more than 10% during the learning phase. Google tells you to judge Smart Bidding over periods with at least 30 conversions, 50 for target ROAS, and calls an App campaign bid constrained when the achieved CPA closely tracks or intermittently exceeds the target. Meta’s own page says an ad set usually exits learning after about 50 results in the week after its last significant edit, which is a Meta number, not a law. Any comparison that spans a significant edit is confounded, so wait one learning cycle before you judge it.

Too many campaigns. In one US account four of eight campaigns had never cleared 50 optimization events a week and produced 70 between them, one campaign’s worth of signal spread across four. They took 23% of the budget and returned 54% at day 28 against 80% for the other four, and 54% against 75% with launch age held constant. That is one account, and budget followed performance in it. Treat the 50 event count as a check to run first and not as a rule.

Is it the season?

Only if you can show it against your own baseline. I found no primary dataset on mobile CPM seasonality, and the Q4 premiums quoted by agencies and tool vendors disagree with each other by more than a factor of two, so none of them appears here. The check is the same calendar weeks of last year, by country and placement, normalized for your own spend. CPM up with click rate and click to install rate steady is consistent with competition. CPM up with click rate down is a creative question with a seasonal excuse attached. Season moves the product side too, so a fitness app’s January trial rate rising is season in the numerator.

What does the decision tree look like?

  1. Did the measurement change? SDK, MMP settings, attribution windows, conversion value schema, connectors, currency, gross or net. If yes, fix it and set a new baseline before any budget decision.
  2. Are the cohorts the same age? If not, rebuild by install week at a fixed day.
  3. Did CPI move, and which input? CPM points at competition, mix or signal quality. Click rate or IPM points at creative and placement. Click to install points at the store page.
  4. Did conversion after install move? Install to trial, trial to paid, payer rate, by app version, against the release log.
  5. Did value per payer move? Price, plan mix, refunds, renewals, order value, ad eCPMs, the mediation setup.
  6. Is the gap only between the platform and the MMP? Then it is windows or duplicates, not users.
  7. Nothing moved on matched cohorts and trusted data? Then you are at the margin of demand at this efficiency, and the next step is a holdout or a geo test, then a budget decision.
Symptom Likely causes Where to look The test
CPI up, CPM up, click rate flat Competition, season, country or placement mix, lower predicted action rate CPM by country and placement, same weeks last year, within versus mix split Hold the mix constant and compare again
CPI up, click rate or IPM down Creative wearout, placement shift, audience expansion IPM by creative age and frequency, spend concentration, date of last new concept A controlled refresh inside the same structure
CPI up, click to install down Store page, rating, ad to page mismatch, featuring ended Click to install rate by source, release dates A product page test
CPI flat, ROAS down Paywall, price or onboarding change, payment failures, event bug Install to trial and trial to paid by app version Version split cohorts, event audit
ROAS down on iOS only SKAN or AdAttributionKit schema or window change, anonymity tier drop Postback counts by value, share of null values Revalidate the schema
Platform conversions drop on one date Attribution window removed, connector change Conversions by attribution window Pull supported windows, compare with the MMP
Platform purchases above MMP purchases Window mismatch, installs credited to views, two pipelines Platform versus MMP by event and window Align windows, one event pipeline
Blended ROAS down after scaling Young cohorts, or real diminishing returns ROAS at the same age by install week and spend tier Compare marginal cohorts at the same age
ROAS up while CPI up Mix shifted toward countries or audiences worth more Value per install by country None. Do not cut on CPI alone

When is cutting the budget the right call?

My rule is that I cut when cohorts of the same age miss the CPA ceiling on reconciled data, and nothing in the change log explains the miss. The fitness app is the closest case I have, with a $15 target standing in for a ceiling. By day 25 the cost per trial sat at $30 against a $15 target, on measurement we had set up across Meta, App Store Connect, RevenueCat and Mixpanel. More than 40 creatives had run and the algorithm had put 90% of spend on two that still missed, and the diagnosis was the product serving two audiences with one funnel. We paused, with the product work and the return conditions written down. The $30 cost per trial was a real floor, and small tweaks would not have moved it.

What a cut does not do. It does not fix a paywall regression, since ROAS stays low at any spend. It does not fix an event mapping error, since the platform keeps optimizing toward the wrong signal. It does not fix wearout, since lower spend may trim frequency for a week and refreshes nothing. It does not fix young cohorts, since it only improves the blended number cosmetically. And a large edit on Meta, TikTok or Google can restart learning and add a second problem to the first. Where the decision is big, a holdout or a geo test comes before the cut, the way I would run one for a network.

What should you check before the next budget change?

  1. Freeze and log. Every change in the last two to three weeks, from the app, the store page, the events, the attribution settings and the campaigns.
  2. Reconcile. Platform against MMP against RevenueCat for installs, trials and purchases. Windows aligned, currency and basis confirmed, no duplicate events.
  3. Check the windows. No report still asking for a window the platform no longer returns.
  4. Check the iOS signal. Postback volume, the share of null or coarse values, any schema or window edit.
  5. Rebuild on cohorts of the same age. D0, D7 and D28 by install week, never a blended calendar number.
  6. Split CPI. CPM, click rate or IPM, and click to install, by country and placement.
  7. Split mix from rate. The change inside each country against the shift of spend between countries.
  8. Check the funnel by app version. Install to trial, trial to paid, payer rate, value per payer, renewals, against the release log.
  9. Check the creatives. IPM by creative age and frequency, spend concentration, the date of the last new concept.
  10. Check the learning state. If a significant edit sits inside the comparison window, wait one cycle.
  11. Check the season against last year, or drop the hypothesis.
  12. Then decide, on marginal ROAS at the same age against the ceiling, with a holdout first when the number is large.

If you are on step one and the log is empty because nobody kept one, the growth audit is where I rebuild it for an account and run the twelve checks, and you can book it on its own at any spend level.

Sources and scope

I had each page checked on 5 October 2026. Platform documentation changes without notice, so check the date before you quote a threshold or a window. The CPI split, the paywall example, the country mix example and the scaling example are arithmetic on labeled assumptions, not an account. The cases I link to are accounts I worked on, one account each, and not controlled experiments. Meta’s help pages block automated retrieval, so I had them opened in a browser.

Questions people ask

My CPI is rising and I cannot tell whether it is creative, attribution or targeting. How do I find out?

Split CPI into its three inputs, which are CPM, click rate and click to install rate. Creative shows up as a falling click rate, a weak store page as a falling click to install rate, and targeting or auction changes as a rising CPM or a shift in country and placement mix. Attribution is a separate check, so compare the platform's installs with the mobile measurement partner's (MMP) before you believe either.

We spend $50K a month on ads and ROAS has not improved. What should I check first?

Check the change log first, then the cohort age. List every change from the last two to three weeks across the app, the store page, the events, the attribution settings and the campaigns. Then rebuild ROAS by install week at the same age, because scaling spend lowers blended ROAS on its own while the new cohorts are young. Only after both do I compare marginal ROAS at the same age with the CPA ceiling.

Can ROAS fall while CPI stays flat?

Yes. ROAS at any age is value per install divided by CPI, and every term in value per install sits after the ad: trial start, trial to paid, price, renewals, order value, ad revenue. In one of my game accounts D0 ROAS halved from 22% to 11% while CPI barely moved, because value per buyer fell from £29 to £18.

Is my CPI rising because of creative fatigue?

Creative fatigue, also called wearout, is the cause only if the click rate or IPM, installs per thousand impressions, of specific creatives fell as their frequency rose, with CPM steady. That is the observable symptom. The best experimental evidence says wearout varies widely by campaign, so test it with a controlled refresh inside the same structure instead of assuming it from the calendar.

When is cutting the budget the right answer?

Cutting the budget is right when cohorts of the same age miss the CPA ceiling on reconciled data and nothing in the change log explains the miss. A cut does not fix a paywall regression, an event mapping error, creative wearout or young cohorts. It changes delivery, and a large edit can send the campaign back into learning.