01 / THE THREE DIFFICULTY SIGNALS

Why rating count alone isn’t enough to measure keyword competition

Sometimes an app with 200,000 ratings ranks #3 for a niche search term purely by accident—because one word in its description or category matched loosely, while its 30-character App Title targets a completely different topic. A newer app whose Title explicitly matches that niche phrase can often outrank a giant that isn’t intentionally targeting the query.

To capture both authority and intentional targeting, Searchbop’s [`difficultyFrom()`](file:///Users/tarik/Desktop/TengrX-SEO/packages/core/src/aso/score.ts#L37-L50) function inspects the top 10 results returned by Apple for that country and combines three components:

Component Weight Exact Mathematical Formula What It Measures in the Top 10
1. Rating Volume Strength 55% clamp(mean(log10(1 + ratingCount)) / 6) Logarithmic authority of the top 10 apps (`1,000,000` ratings = `1.0`; `1,000` ratings = `0.5`; `10` ratings = `0.17`).
2. Rank-Weighted Title Match 30% Harmonic rank weight 1 / (i + 1) × Title match (1.0 exact phrase, 0.6 all words present, 0.3 partial word hit, 0.0 none) Whether the `#1`, `#2`, and `#3` apps are intentionally targeting this exact keyword in their 30-character App Name.
3. Rating Quality 15% clamp((mean(averageUserRating) - 3) / 2) across rated apps User satisfaction wall (`4.8★` average is much harder to beat on tap-to-install conversion than `3.4★` apps).
02 / GUARDING AGAINST FALSE “EASY” SCORES

Why fewer than 3 App Store results must never be labeled “Difficulty: 0”

When an obscure typo or ultra-long query returns zero, one, or two apps on the App Store, naive scripts calculate `difficulty = 0` and flag the term as an “Easy Win.” In reality, fewer than 3 results (`MIN_RESULTS_FOR_DIFFICULTY = 3`) means the query has no established storefront SERP—often because nobody searches that phrasing or Apple’s search parser failed to match any category.

When `results.length < 3`, Searchbop returns `difficulty: null, state: "no_data"` and withholds the Opportunity score so your Quick Wins filter never fills up with ghost keywords.

03 / THE OPPORTUNITY FORMULA

How Searchbop calculates your 0–100 Opportunity Score

Once both Popularity (`P`) and Difficulty (`D`) are known, [`opportunityFrom()`](file:///Users/tarik/Desktop/TengrX-SEO/packages/core/src/aso/score.ts#L53-L59) computes a single prioritization score:

EXACT OPPORTUNITY SCORE IMPLEMENTATIONpackages/core/src/aso/score.ts
export function opportunityFrom(k: {
  popularity: number | null;
  difficulty: number | null;
  relevance?: number | null;
  rank?: number | null;
}): number | null {
  if (k.popularity == null || k.difficulty == null) return null;
  let score = Math.sqrt(k.popularity * (100 - k.difficulty)) * (k.relevance ?? 1);
  if (k.rank != null && k.rank >= 4 && k.rank <= 30) score *= 1.15; // Striking-distance boost
  if (k.popularity < 20) score *= 0.5;                              // Low-volume dampener
  return Math.round(Math.min(100, score));
}
04 / 91-COUNTRY RANK TRACKING

How country and language parameters work on Apple’s Store Search API

To check where your app ranks in a specific country (`US`, `TR`, `DE`, `JP`, `BR`, etc.), Searchbop queries `https://itunes.apple.com/search` with `entity=software`, `limit=200`, `country={cc}`, and—crucially—the storefront’s explicit `lang={lang}_{cc}` parameter ([`itunes.ts`](file:///Users/tarik/Desktop/TengrX-SEO/packages/core/src/aso/itunes.ts#L50-L63)).

Why does `lang` matter? Without the `lang` parameter, Apple’s public Search API frequently returns English localized app titles even when querying a non-English storefront, which distorts title-match difficulty calculations. And for the few storefronts whose regional locale string Apple’s endpoint rejects with `HTTP 400` (such as `ar_dz` or `he_il`), Searchbop automatically retries without `lang` so every single one of the 91 countries resolves cleanly.

Honest boundaries: Public API vs. on-device personalization

Why your phone may show a slightly different rank: Apple’s public `itunes.apple.com/search` endpoint reflects unpersonalized storefront rankings and updates at a `3,000 ms` pace (~20 queries/minute). On a physical iPhone signed into an Apple ID, the App Store personalizes results slightly based on prior installs and device context. Tracking unpersonalized storefront ranks over time in `asoRankHistory` gives you a consistent baseline across releases.

Research context & search queries covered on this page Difficulty & Ranks · P1

Cluster & intent: aso-difficulty-ranks (Informational / Commercial · P1) · Target queries: app store keyword difficulty, how to check app store ranking, ios keyword rank tracker, app store competitor keyword research.