I shipped an iOS app three weeks ago. It has 1 review.

Not "1 star" — one single review, from one person. Downloads are somewhere between zero and a rounding error. The app works fine. People who use it like it. Nobody finds it.

Instead of guessing, I pulled data on the entire category and looked for the pattern. Here's what the numbers said, including the part I didn't want to hear.

The setup

The app is a screen time blocker. The pitch: it's for adults who want to block themselves — no account, no cloud, no monitoring dashboard, everything on-device via Apple's Screen Time API.

I thought that positioning was strong. I had evidence for it, too: the biggest "accountability" app in the category has 58k ratings at 4.3★, and its 1-star reviews are full of things like "My parents installed this for me… I cannot use the internet without fear of being monitored." There's clearly a group of people who want the opposite of that.

So: real pain, differentiated position, working product. And nothing happened.

Step 1: check whether anyone can find it

The iTunes Search API is public and free, no key required. You can query the exact ranking for any keyword:

import json, urllib.parse, urllib.request

def rank_for(term, app_name, country="us", limit=50):
    qs = urllib.parse.urlencode({
        "term": term, "country": country,
        "entity": "software", "limit": limit,
    })
    req = urllib.request.Request(
        "https://itunes.apple.com/search?" + qs,
        headers={"User-Agent": "Mozilla/5.0"},
    )
    results = json.load(urllib.request.urlopen(req, timeout=15))["results"]
    for i, app in enumerate(results, 1):
        if app_name.lower() in app.get("trackName", "").lower():
            return i
    return None  # not in top `limit`

Enter fullscreen mode Exit fullscreen mode

I ran this against every keyword I'd been targeting:

Keyword Rank
app blocker not in top 50
screen time not in top 50
focus not in top 50
digital detox not in top 50
doomscroll not in top 50
screen time detox #21

One keyword, at #21. The only reason that one works is that the phrase is literally in the app's title — pure relevance matching, no ranking strength behind it.

App Store ranking is roughly relevance × downloads × ratings. Two of my three factors were zero. The app wasn't competing badly; it was invisible.

Worse, when I re-checked a few days later that single keyword had drifted #21 → #23 → #26. Without downloads feeding back in, even the one ranking I had was decaying.

Step 2: is this just what new apps look like?

Reasonable hypothesis: everything new is invisible, you grind it out. So I pulled the whole category and filtered for apps that shipped after I would have, but already had traction.

def newcomers(apps, since="2025-01-01", min_ratings=50):
    out = []
    for a in apps:
        if a.get("releaseDate", "")[:10] >= since and a.get("userRatingCount", 0) >= min_ratings:
            out.append((a["userRatingCount"], a["releaseDate"][:10], a["trackName"]))
    return sorted(out, reverse=True)

Enter fullscreen mode Exit fullscreen mode

Across 204 apps in the category, 103 had launched since the start of 2025. Plenty of them had real traction. So no — being new isn't the explanation.

Here's the top of that list:

App Launched Ratings
Unrot: Earn your Screen Time 2025-06 56,183
Brainrot: Screen Time Control 2025-05 17,885
Pushscroll: Exercise To Scroll 2025-06 16,709
PushUp Time: App Blocker 2025-09 11,530
FocusFlight — Deepfocus Timer 2025-01 8,792
Focus Friend, by Hank Green 2025-07 4,147
touch grass: screen time limit 2025-03 2,977

Read the names again. That's the whole finding.

The pattern

Every single one of them has something you can say out loud in one sentence, to a person, and have them react:

  • You do push-ups to unlock Instagram
  • You have to earn your screen time
  • Named after the exact slang the target user already uses (brainrot, touch grass)
  • Backed by someone with an audience (Hank Green)

Mine, said out loud: "it's a screen time blocker that runs on-device and doesn't require an account."

Nobody has ever repeated that sentence to a friend. It's a specification, not a story. It answers "what are its properties" when the only question that spreads is "what does it make you do."

The privacy angle is real and I'd build it that way again. But it turns out to be a reason to trust an app you already heard about — not a reason to hear about it. I'd made my only differentiator invisible by definition: "nothing leaves your device" produces no artifact, no screenshot, no story.

The ones that grew didn't out-market me. They shipped a mechanic that generates its own distribution. Someone doing push-ups to open TikTok is a video. "No account required" is not a video.

What I'd tell past me

Ask "what's the screenshot?" before writing code. Not "what's the feature list" — what is the concrete artifact a user would send to another person? If you can't answer that, you don't have a distribution plan, and no amount of ASO tuning will retrofit one.

Correct ≠ compelling. I optimized hard for being right about privacy and never checked whether being right was interesting. Those are independent variables and I assumed the first implied the second.

Check keyword ranks on day one, not week three. Two lines of Python against a public API. I built for weeks on the assumption that shipping put me in the game. It didn't — I was never in the search results at all.

Look at what the newcomers did, not what the leaders did. The category leaders won years ago under different conditions and their playbook doesn't transfer. Apps that broke in within the last 12 months faced the same App Store you're facing right now.

Where I am now

Still 1 review. Since drafting this I've kept the rank check running daily: that one keyword went #21 → #26 → #22 and is now #24. Ten days of content and link work moved it exactly nowhere, which is a fairly loud confirmation of the diagnosis above rather than a refutation of it.

I'm not going to pretend this has a happy ending yet — the fix is adding a mechanic worth telling someone about, and that's a product change, not a marketing one.

Two things you can take without installing anything:

  • The rank check, packaged properly: asorank — single file, stdlib only, no API key and no account. python3 asorank.py --id <appid> --terms "app blocker,screen time" prints a table. MIT, 31 tests. It exists because three things bit me that the ten-line version above doesn't handle: Apple serves HTTP 200 for App Store URLs that don't exist (so status-code link validation silently passes dead links), apps aren't on every storefront, and rapid queries get 403'd.
  • A screen time calculator I built while trying to find a "screenshot" for this idea. It converts hours/day into waking years lost, not calendar years — 2h/day is 1/12 of a day, which is dismissible, but 1/8 of your conscious life, which isn't. No signup, runs in the browser.

The app itself is SproutGuard, free, if you want to see the "correct but boring" version for yourself.

If you're building something in a crowded category: run the rank check before you ship. It takes ten minutes and it would have saved me three weeks of building the wrong thing well.