⏱️ Lectura: 12 min

Google charged Nick Abe, creator of the puzzle game Dayzle, for installs his own admin dashboard never saw. Over two weeks of running the campaign, he spent CA$220 on Google Ads and was billed for 56 installs, but only 13 came from real people.

📑 En este artículo
  1. TL;DR
  2. What happened
  3. Background and history: how an install bot farm operates
  4. Technical details and performance
  5. How to start auditing your own campaign
  6. Impact and analysis
  7. What’s next
  8. Frequently Asked Questions
    1. What exactly is a bot farm in mobile advertising?
    2. Why doesn’t Google filter this out automatically?
    3. Does changing the target cost per install help filter out bots?
    4. Does this apply to all app categories, not just games?
    5. Which conversion event is hardest to fake?
    6. How do I claim fraudulent installs with Google?
  9. References

The rest carried the classic signature of a bot farm: devices that open the app once, never touch a single screen, and disappear forever. The case exposes a risk that any indie developer in Latin America working with a tight budget can suffer without ever noticing.

TL;DR

  • Nick Abe spent CA$220 on Google Ads over two weeks promoting his Android app Dayzle.
  • Google billed 56 installs; Nick’s actual dashboard confirmed only 13 genuine users.
  • 33 of those installs showed the same pattern: the app opened for 0 seconds and was never opened again.
  • On a single day, 20 of 21 installs corresponded to an app version that Play Store no longer distributed.
  • Those 20 installs came from 28 different phone models spread across 19 states.
  • 7 additional installs came from countries outside the campaign’s geographic target.
  • The 13 real users completed 92 games of Dayzle combined.
  • Nick changed the conversion goal from “open the app” to “win a puzzle” to make fraud more expensive.

What happened

Nick Abe runs Dayzle, a puzzle game for Android, and launched a Google Ads campaign with a CA$40 daily budget targeting installs. With a target cost per install of US$1.50, Google was barely spending the budget: the system couldn’t find enough installs at that price.

As a test, Nick removed the target cost cap. Spending immediately doubled to CA$80 daily, and Google reported 21 installs that day. Dayzle’s admin dashboard, on the other hand, showed just one real install.

⚠️ Watch out: removing the cost-per-install cap didn’t improve traffic quality: it just gave the bot farm more budget to keep generating fake installs faster.

Reviewing the raw analytics data, Nick found the explanation: those 21 installs corresponded to new Android devices, and 20 of them were running an old version of the app that Google Play had stopped distributing days earlier. That’s impossible if the real installer was Play Store: the only way to have that version is to have installed it from a previously saved APK file.

Even so, all 20 devices reported Google Play as the install source. Each one opened the app exactly once, didn’t interact with a single screen, and never opened it again. Among those 20 devices there were 28 different phone models spread across 19 states, an enormous variety for a group that did exactly the same thing on the same day.

By the end of the two-week campaign, the tally was: 56 billed installs, 33 with that same ghost pattern, 7 more from countries outside the campaign’s geographic targeting, and 13 real people. Those 13 people, combined, completed 92 games, the only sign that the product actually works for someone using it for real.

Bot farm generating fake installs in an Android app
20 of 21 installs that day came from an app version that Play no longer distributed. Foto de Sherebyah Tisbi en Unsplash

Background and history: how an install bot farm operates

Click fraud has existed since programmatic advertising started paying per event instead of per impression. What’s new in the Dayzle case is that the fraud migrated from the click to the install: in cost-per-install (CPI) campaigns, a bot that installs the app once is cheaper to manufacture than a sustained click, and Google bills the same either way.

The mechanism Nick describes has a perverse logic. Google Ads optimizes ad delivery toward whatever goal the advertiser sets: if the goal is “installs”, the system learns which inventory generates more installs and sends it more budget. A bot farm that watches the shortest video in the ad group without clicking, then installs the app from a local copy instead of downloading it from Play Store, generates a valid conversion in the algorithm’s eyes. The more installs the farm racks up, the better the performance profile Google assigns it, and the more ads it sends its way. It’s a loop that guarantees a small advertiser’s budget burns up with no return.

flowchart TD
    A["Bot farm watches the shortest video in the ad group"] --> B["Installs the app from a saved APK, not from Play Store"]
    B --> C["Google Ads logs view + install as a valid conversion"]
    C --> D["The algorithm learns and sends more budget to that profile"]
    D --> A

This loop explains why removing the cost-per-install cap made things worse instead of better: Google interpreted the lack of a cap as a green light to buy more of what was already working, and what was working was the bot farm.

Technical details and performance

The technical fingerprint of a fraudulent install is rarely subtle once the right data sources are cross-referenced. In Dayzle’s case, the clearest signal was the app version: the suspicious devices were running a build that Play Store had pulled days earlier, something that only happens if the APK was manually sideloaded instead of downloaded from the store.

The second signal was installer attribution. Android’s Install Referrer API lets any process with shell access (via ADB, for example, or a rooted device with Frida/Xposed) write a fake referrer value declaring Google Play as the source, even though the actual install came from a file shared across dozens of phones in the farm.

The third signal was session behavior: 0 seconds of use, no screens viewed, zero return visits. Combined with the artificial diversity of 28 device models across 19 states on the same day, the technical conclusion is hard to avoid.

MetricReal userBot farm install
Time in appMinutes to hours, repeated sessions0 seconds, a single open
Installed versionThe latest published on Play StoreA version Play already stopped distributing
Device diversityConsistent with your real audienceDozens of different models on the same day
Installer attributionLegitimate Google Play StoreManually loaded APK but reported as Google Play
Geographic targetingWithin the campaign’s target countryInstalls from countries outside the target

To detect the pattern without relying only on intuition, it helps to automate the comparison between what Google Ads reports and what your own backend or Firebase logged. A simple Google Ads Script is enough for a first filter:

function main() {
  var report = AdsApp.report(
    "SELECT CampaignName, Device, Conversions, AverageCost " +
    "FROM CAMPAIGN_PERFORMANCE_REPORT " +
    "WHERE CampaignName = 'Dayzle - Android Installs' " +
    "DURING LAST_14_DAYS"
  );
  var rows = report.rows();
  while (rows.hasNext()) {
    var row = rows.next();
    Logger.log(row.Device + ": " + row.Conversions + " conversions at $" + row.AverageCost);
  }
}

This script runs weekly inside the Ads Scripts interface and lists conversions by device type for a specific campaign. Any isolated spike in a single model, time window, or country outside your targeting deserves a manual review before increasing budget.

Analytics dashboard showing zero-second sessions
0-second sessions: the simplest signal for detecting fraudulent traffic. Foto de Roger Starnes Sr en Unsplash

How to start auditing your own campaign

You don’t need to be a big company to apply the same process Nick Abe used. Here are the concrete steps:

  1. Export install and session events from Firebase Analytics or your analytics SDK, including timestamp, device model, and session duration.
  2. Cross-reference that export against Google Ads’ click report (click_view in the Google Ads API) using gclid as the common key.
  3. Flag as suspicious any record with a session duration of zero, an outdated app version, or a country outside your targeting.
  4. If the pattern repeats, file an invalid traffic claim through the Google Ads help center.
  5. Change the conversion event your campaign optimizes for to something a simple script can’t cheaply fake, like completing a level or winning a game.

For step 2 in a real project, a Node.js script that combines both sources looks like this:

const { GoogleAdsApi } = require("google-ads-api");
const admin = require("firebase-admin");

const client = new GoogleAdsApi({
  client_id: process.env.GADS_CLIENT_ID,
  client_secret: process.env.GADS_CLIENT_SECRET,
  developer_token: process.env.GADS_DEV_TOKEN,
});

async function flagSuspiciousInstalls(customerId, refreshToken) {
  const customer = client.Customer({ customer_id: customerId, refresh_token: refreshToken });

  const clicks = await customer.query(`
    SELECT click_view.gclid, segments.device, segments.date
    FROM click_view
    WHERE segments.date DURING LAST_14_DAYS
  `);

  const db = admin.firestore();
  for (const click of clicks) {
    const session = await db.collection("app_sessions").doc(click.click_view.gclid).get();
    const seconds = session.exists ? session.data().duration_seconds : 0;
    if (seconds === 0) {
      console.log(`Suspicious: gclid=${click.click_view.gclid} device=${click.segments.device}`);
    }
  }
}

The script goes through the clicks Google Ads reported over the last two weeks and looks up, for each gclid, the matching session document in Firestore. A 0-second duration repeated across different devices is the same fingerprint that gave away Dayzle’s bot farm.

If you’d rather work with the full history in SQL instead of iterating row by row, you can export your Google Ads account to BigQuery using the Google Ads API and the Google Cloud CLI:

# Windows (PowerShell)
(New-Object Net.WebClient).DownloadFile("https://dl.google.com/dl/cloudsdk/channels/rapid/GoogleCloudSDKInstaller.exe", "$env:Temp\gcloud-installer.exe")
& "$env:Temp\gcloud-installer.exe"
gcloud init

# macOS
brew install --cask google-cloud-sdk
gcloud init

# Linux (Debian/Ubuntu)
echo "deb [signed-by=/usr/share/keyrings/cloud.google.gpg] https://packages.cloud.google.com/apt cloud-sdk main" | sudo tee /etc/apt/sources.list.d/google-cloud-sdk.list
sudo apt-get update && sudo apt-get install -y google-cloud-cli
gcloud init

With the export active, confirm the data is arriving by running bq ls your_project:google_ads_dataset and checking that the p_ads_ClickStats_* table has rows dated today before building queries on top of it.

💡 Tip: keep a history of app version by device from day one of your campaign. Without that reference data, there’s no way to later detect that an install arrived with a version Play had already pulled.

Impact and analysis

The Dayzle case is small in dollar terms (CA$220 over two weeks) but significant in proportion: if 60% of an indie developer’s spend goes to bots, any business decision based on that cost per install becomes distorted. Raising budget, pausing channels that “don’t convert”, or calculating return on investment with those numbers leads to the wrong conclusions.

Nick Abe reasons that if a bot farm found it profitable to target such a small budget, larger apps are likely receiving much more of this traffic without noticing, simply because volume dilutes the pattern. An advertiser spending millions of dollars a month rarely audits install by install the way Nick did with his 56 conversions.

The cost asymmetry is at the root of the problem: generating a fake install by software is cheap, while verifying one requires cross-referencing several data sources that almost no small team has time to maintain.

What’s next

Nick is still waiting for Google’s response to the invalid traffic form he filed, and promised to report back if he gets a refund. In the meantime, he’s already changed his campaign’s optimization goal from “open the app” to “win a puzzle”: a much more expensive event for a script to fake, since it requires solving real content inside the game.

The strategy doesn’t eliminate fraud, it just makes it more expensive. For an app the size of Dayzle, making it more costly to attack than the neighboring competitor may be enough protection. For larger apps, investing in deep event verification is probably already worth it, though Nick has no way to confirm that with his own data.

📖 Summary on Telegram: View summary

Try it yourself: export the last two weeks of installs from your Google Ads campaign and cross-reference them by session duration before approving your next budget increase.

Frequently Asked Questions

What exactly is a bot farm in mobile advertising?

It’s an operation that uses many devices, real or emulated, to generate fake clicks or installs that get billed as legitimate conversions inside an ad platform like Google Ads.

Why doesn’t Google filter this out automatically?

Google does filter out some invalid traffic detected in real time, but the Dayzle case shows that installs with false Play Store attribution and no obvious signs of automation can pass the initial filter and require a manual review afterward.

Does changing the target cost per install help filter out bots?

Not necessarily. In the case described, removing the cost cap doubled daily spending and increased reported installs, but the proportion of fraudulent installs didn’t drop.

Does this apply to all app categories, not just games?

Yes. The mechanism depends on the type of conversion event the campaign defines, not the app’s category: any CPI based on an event that’s easy to fake (opening the app, a click) is an attractive target for a bot farm.

Which conversion event is hardest to fake?

Events that require completing an action with real business logic inside the app, like finishing a level, completing a purchase, or reaching an advanced step in a flow, are more expensive to automate than simply opening the app.

How do I claim fraudulent installs with Google?

Google Ads has an invalid traffic report form accessible from its help center; you need to attach evidence of the discrepancy between what was billed and what your own analytics recorded.

References

📱 Enjoy this content? Follow @programacion on Telegram for daily tech content in Spanish: quick summaries, fresh content every day.

Imagen destacada: Foto de NordWood Themes en Unsplash

Categories: Noticias Tech

Andrés Morales

Developer and AI researcher. Writes about language models, frameworks, developer tooling, and open source releases. Covers ML papers, the tech startup ecosystem, and programming trends.

0 Comments

Leave a Reply

Avatar placeholder

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.