How to Read a Mobile Install-Fraud Report

A mobile install-fraud report is your MMP's ledger of installs it refused to attribute to a paid source, tagged with a machine-readable reason code. Read it as a to-do list, not a verdict: each rejection reason maps to a specific on-device behavior, a specific dispute you can file, and a specific person you escalate to. The trick is knowing which code means "your partner is stealing credit" versus "the OS just did something weird."

I've spent a lot of hours in these reports, mostly because a partner disputed a number and I had to explain, line by line, why 8,000 of their installs got zeroed out. So here's the field guide I wish someone had handed me: every common rejection label, decoded into what it means, what you do about it, and who you drag into the thread.

First, some scale, because the reports feel less like paranoia once you see the totals. Business of Apps's 2025 ad-fraud roundup cites Juniper Research pegging mobile ad-fraud losses near $17.2 billion for the year, and notes Fraudlogix data showing 31% of global mobile app traffic is invalid. On the install side specifically, AppsFlyer's 2025 fraud data (summarized by RocketShip HQ) puts roughly 22% of non-organic installs as carrying fraud signals, up from about 17% in 2022, and Android runs about 4.5x hotter than iOS. If your report is quiet, that's usually a sign you haven't turned the detection on, not that you're clean.

Rejected vs. blocked vs. flagged: three different words

Before the glossary, get the vocabulary straight, because vendors use these interchangeably and it causes real arguments.

Blocked means the fraud engine caught it in real time and never attributed it. The install still happened on a device somewhere, it just doesn't count against your budget. Rejected (post-attribution) means it was attributed first, then clawed back later when a pattern emerged across a batch, and this is the one that makes your dashboards change retroactively and makes partners furious. Flagged means suspected but still counted, sitting in a "for your review" bucket. When a partner says "you rejected 8,000 installs," step one is always asking which of the three they mean. Half the time the fight evaporates there.

The rejection-reason glossary

Here's the core. I've grouped the labels by what actually happened on the device, since the vendor names drift (AppsFlyer, Adjust, Singular, and Kochava all coin their own strings for the same underlying behavior).

Rejection reason What it actually means What you do Escalate to
Short CTIT / click injection A click fired during your install, not before it Pull the CTIT histogram for that sub-pub, dispute if the <10s bucket is fat The network's fraud/AM contact
Click flooding / click spamming (distribution anomaly) Partner sprayed clicks to catch organic installs on last touch Compare their click-to-install ratio to your median, then renegotiate to view-through or cut Your media buyer + the network
Anonymous IP / untrusted device Install came from a VPN, Tor, or datacenter range Accept the block, ask the partner where the inventory sits The network (sourcing question)
New-device-rate anomaly / device farm A burst of never-before-seen device IDs from one source Check reset rate vs. your baseline, likely a reset farm Fraud vendor + network
SDK spoofing / fake install A postback arrived with no real device behind it Verify SDK signing is on, this one's non-negotiable Fraud vendor, then legal/finance
Install hijacking Real user, real install, falsified last engagement Confirm reattribution to prior contributor, adjust payout The hijacking network
Bots / emulators Automated installs, no human session depth Look at post-install event depth (usually zero) Fraud vendor + network
Hyper-engagement / too many clicks Same click sent many times before the install Dedup at the network, often a broken integration, not malice The network's tech contact

Now the detail, because a table row won't win you a dispute.

Short CTIT (click injection)

Click-to-install time is the gap between the recorded click and the first app open. On a real click, someone taps an ad, waits for the store, downloads, opens. That's tens of seconds to several minutes. Click injection malware sitting on the device watches for the install broadcast and fires a fake click milliseconds before the app opens, so it steals last-touch credit. The tell is a CTIT distribution crushed against zero. Opticks Security's 2025 write-up puts a usable rule of thumb on it: if a single sub-publisher shows more than 40% of installs under 10 seconds, that's almost certainly injection, not luck.

What to do: don't argue the aggregate. Pull the raw CTIT values for the disputed source and show the histogram. A real source has a hump somewhere in the 30-second-to-few-minutes range. An injecting source has a spike at zero and nothing else. This is an Android problem specifically. The mechanism relies on the install-referrer broadcast, and here's a doc ambiguity worth flagging: Google's Play Install Referrer docs describe the API surface but don't promise timing guarantees, so "how fast is too fast" is empirical, not spec'd. Testing shows the sub-10-second floor holds up. Escalate to the network's account manager with the histogram attached. It's the fastest dispute to win because the picture is unambiguous.

Click flooding (a.k.a. click spamming)

This one's sneakier and it's the reason last-click attribution is a mess. The fraudster doesn't inject anything. They just fire an enormous volume of clicks for users they never actually drove, betting that some of those users install organically later. When the organic install lands, their stray click is the last touch, and they bill you. As one Business-of-Apps analysis of MMP evasion put it, a network throwing 500,000 clicks to catch 50 installs is spraying, not driving demand.

The MMP catches this with distribution analysis. Adjust's Distribution Modeling looks at the shape of the click-to-install time distribution for a source and flags the flat, unnaturally spread-out curve that spamming produces (Adjust pairs it with Hyper-Engagement filtering, and notes the two must be enabled together, so you can't run one alone). What you do: compute click-to-install ratio per partner and compare to your own median. A source that's 10x your typical CTI ratio is buying lottery tickets with your budget. This is a business conversation more than a technical one, so loop in the media buyer, because the fix is usually renegotiating that partner to view-through terms or dropping them, not filing a bug.

Anonymous IP and untrusted devices

Device farms and bot operations route through VPNs, Tor exit nodes, and datacenter IP ranges to hide their footprint. Adjust's Anonymous IP filter cross-checks every install against MaxMind's anonymous-IP database and dumps anything from an anonymizing service into an "Untrusted Devices" bucket. This is one of the cleaner signals. A residential user installing your fitness app is not coming through a Tor exit node.

The action here is mostly acceptance plus a sourcing question. You don't dispute an anonymous-IP block, you ask the partner why their inventory sits behind datacenter IPs. Sometimes there's a legit answer (an operator proxy, a specific carrier setup), more often there isn't. Watch for false positives on legitimately privacy-conscious users, though. The same filter that catches a farm can catch a real person on a corporate VPN, so if the volume is small and the post-install behavior is healthy, don't torch it.

New-device-rate anomaly and device farms

A device farm is a rack of real (or reset) phones tapping ads all day. The signature in your report is a burst of device identifiers your system has never seen, concentrated in one source over a short window. Legit sources have a steady trickle of new devices. A farm doing ID resets to look "fresh" produces a spike. AppsFlyer's Protect360 raw-data reports expose the device-level detail so you can see the new-device rate per source rather than trusting the summary count.

What you do: pull the new-device rate for the flagged source and compare it against your organic baseline for the same geo. If organic new-device rate in that country is, say, 60% and this source is showing 98%, that gap is your evidence. Escalate to both your fraud vendor (to confirm the pattern) and the network (to explain it). Device-farm disputes take longer than CTIT ones because "these are all real devices" is technically true. The devices are real, the intent isn't.

SDK spoofing and fake installs

This is the one that isn't a gray area. SDK spoofing is a fabricated postback: no install happened at all, the fraudster reverse-engineered your SDK's payload and forged the network calls to mint installs and even in-app events out of nothing. There's no device, no user, no session. It's counterfeiting.

The only real defense is cryptographic. SDK signing, or secure attribution, means each genuine install carries a signature the fraudster can't forge without the key. If SDK signing isn't enabled and you're seeing spoof flags, step one isn't a dispute, it's turning signing on. When you do catch a spoofing source, this isn't a "let's rebalance to view-through" conversation. Loop in finance and, if the volume is material, legal. You're likely dealing with a network reselling forged traffic, and the money should be reversed, not renegotiated.

Install hijacking

Hijacking is the tricky cousin of injection. The user is real, the install is real, but a fraudulent network falsifies an engagement to steal last-touch credit from whoever legitimately drove the user. The important behavior to understand is what the MMP does after it catches this. Per AppsFlyer's Protect360 documentation, a hijacked install isn't just discarded. Attribution is blocked to the fraudulent network and reassigned to the last legitimate contributor, surfaced through the rejected_reason_value field. So a hijack rejection is also a correction: someone else deserves that install.

What you do: verify the reattribution actually landed on the right contributor, and adjust payouts on both sides: claw back from the hijacker, credit the legit source. The rejected_reason_value field is your source of truth for who that is. Escalate to the hijacking network, but arm yourself first, because they'll dispute the reassignment.

Bots, emulators, and hyper-engagement

Two lighter ones to close the glossary. Bots and emulators produce installs with no human depth. Zero or near-zero post-install events, no session length, no retention past day zero. Your fastest confirmation is joining the flagged installs against your event stream: real users do something, bots flatline. Hyper-engagement, meanwhile, means the same click got sent many times before the install. Half the time this is a broken partner integration double-firing, not fraud, so treat it as a tech ticket to the network's integration contact before you assume bad intent.

A triage order that saves time

When a fresh report lands, I don't read it top to bottom. I work it in this order, because it front-loads the cheap wins:

  1. Split the volume by reason code and sort descending. One or two reasons usually dominate, so fix those first.
  2. For the top reason, pull the raw rows, not the summary. Every winnable dispute lives in the device-level detail.
  3. Separate blocked from post-attribution rejected. Only the rejected ones change your historical numbers, and only those cause partner escalations.
  4. Check post-install event depth on the flagged cohort. Zero depth turns a "suspected" flag into a confident call.
  5. Only then open the partner thread, with the histogram or the ratio already attached.

That order matters because most of the reasons are self-evident once you see the raw data, and arriving at the partner's inbox with a picture ends the argument before it starts.

Who owns which escalation

The last piece people get wrong: routing. A rejection dispute dies in limbo when it goes to the wrong desk. My rough map: network account manager for CTIT and hyper-engagement (integration-level, fast), your own media buyer for click-flooding (it's a spend-allocation decision), the fraud vendor plus the network jointly for device-farm and bot patterns (you need the vendor's cross-source view to make the case), and finance or legal for SDK spoofing (it's theft, and it should hit the invoice).

One honest caveat to end on. These reports are one MMP's opinion, built from the signals a single vendor can see. As multiple 2025 analyses of MMP evasion point out, fraudsters calibrate their traffic to sit just under every published threshold, and no single MMP has cross-network visibility, and it evaluates each source in isolation. So a clean report isn't proof of clean traffic, only proof that nothing tripped this set of rules. Read it as your best available evidence, act on the strong signals fast, and stay a little suspicious of the quiet rows. If you want to see where these signals fit in a full measurement stack, the privacy-first attribution reference architecture walks the whole pipeline.

And when a postback shows up three days late and reshuffles a reason code you already disputed — because postbacks arrive whenever they feel like it — just reopen the thread. It happens more than the docs admit.