PeekPanda markpeekpandaDocumentationFor AI ↗Open app

PeekPanda docs

Where the data comes from

Every collection lane behind PeekPanda: which public surfaces are read, how often, what each one contributes, and the three different ways an app enters the catalogue.

Download Markdown ↓

PeekPanda reads public surfaces. Nothing here comes from inside an app, from a panel of installed devices, or from a company's own reporting.

Four lanes bring data in. Each has its own surface, its own schedule and its own limits.

LanePublic surfaceCollected
Ranking feedsApple's public chart feedsEvery 15 minutes, in small batches, until each day's charts are complete
Listing and ratingsApple's public lookupOne reading per app per UTC day, US only
Keyword searchApple's public search and search-suggestion endpointsOn request, paced and budgeted
Public ad librariesAdvertising transparency librariesObserved; each ad carries its own dates

Everything is iOS. There is no Google Play coverage.

Ranking feeds

Apple publishes ordered app charts per storefront. PeekPanda collects them across three dimensions:

  • 6 storefronts: United States, United Kingdom, France, Germany, Brazil, Belgium.
  • 28 categories: Overall plus the 27 App Store genres.
  • 3 chart types: free, paid, grossing.

That is 504 distinct chart lists a day. Two different Apple feed families serve them: a modern JSON feed for the overall free and paid charts, and Apple's older RSS feed for every specific category and for every grossing chart. Both are Apple's own public endpoints. Each list is fetched at a depth of up to 100 ranked apps.

How collection is scheduled. A task fires every 15 minutes and asks the backend to make progress. The backend reserves at most 10 lists that have not yet been snapshotted for the current UTC day, waits 1 second between calls, and fetches them.

The 15-minute clock is a drip, not a reread. Lists already completed for the day are skipped, so the day's work is spread across the day rather than fetched 96 times over. A target that fails is retried at most three times in a day, then left for tomorrow. If Apple rate-limits a call, the whole run stops immediately and backs off rather than pushing harder.

Reading a chart never calls Apple. Every chart page, rank history and category view is served from stored snapshots. There is no button anywhere in PeekPanda that makes a chart go and fetch.

Charts feed the rating tape. Every successful US chart fetch queues that chart's apps for a ratings lookup. This is why the apps you see on leaderboards tend to have the most complete estimate history: being on a chart is what gets an app taped daily.

Sources: packages/libraries/src/domain/app-catalog/apple-charts.contract.ts, apps/backend/src/modules/app-charts/, apps/trigger/src/tasks/apple-charts-refresh.ts.

Listing facts and the rating tape

Apple's public lookup endpoint returns the store listing for a numeric app id. PeekPanda records: name, description, developer name and id, bundle id, version and release notes, price and currency, star rating, lifetime rating count, release date, the date the store says the listing was last updated, languages, genres, minimum OS version, content rating, the website and store URLs, and the icon and screenshot URLs.

Two things come out of this lane.

Listing facts. The descriptive content of a case file, stored with the date they were read. Media is stored as the URLs Apple publishes, not as copied files. PeekPanda points at Apple's images; it does not host them.

The rating tape. The lifetime rating count, recorded once per app per UTC day for the US storefront. That daily sequence is the entire basis of the install estimate. See how estimates are computed.

How collection is scheduled. A task fires every 15 minutes and asks the backend to queue lookups for apps that appeared on a recent US chart but have no tape point for today. Lookups are batched up to 200 app ids per call, spaced 4 seconds apart, and retried with exponential backoff on failure.

Page reads do not wait for Apple. Opening a case file, or pressing refresh on an estimate, can queue that day's lookup. It returns immediately with a pending state and a retry time; the lookup happens in the background. A page never blocks on Apple answering.

One narrow exception, stated so the rule stays true: the add-an-app typeahead in the ASO workstation queries Apple live as you type, rate-limited to 20 searches a minute per person. That is the only place a page waits on the store.

Sources: apps/backend/src/modules/app-catalog/enrichment/, packages/db/src/schema/store-rating-observation.ts, apps/trigger/src/tasks/rating-tape-refresh.ts.

Keyword search and suggestions

Two public Apple endpoints feed everything on the ASO side. Both are US-only, in English.

Search. Apple's public search endpoint returns an ordered list of apps for a query, up to 200 results, each with its name, id, star rating and lifetime rating count. One collection run for one query stores one snapshot. Positions from it are labelled observed_search_api_position for the entire life of the record: they are search-response positions, never native App Store rank.

Search suggestions. Apple's autocomplete endpoint returns the phrases the store offers as you type. For a multi-word keyword, PeekPanda fetches suggestions twice: once for the keyword's first word, and once for the whole phrase. The first tells you where the exact keyword sits in the store's ordering; the second tells you what longer variants the store proposes. Both feed the Demand score in keyword metrics explained.

How collection is scheduled. This lane is demand-driven, not scheduled. Nothing is collected until someone asks. When they do:

GuardValue
Gap between outbound Apple calls4 seconds
Shared daily Apple call ceiling2,500
Search snapshot reused without refetching24 hours
Suggestion snapshot reused without refetching7 days
Refresh jobs one person may start per day40
Cooldown before an app can be refreshed again60 minutes
Queries one refresh job may cover200

Snapshots are shared across everyone. A query collected because one person asked is served to all readers, so popular keywords cost one call, not one per customer. Duplicate refreshes on a fresh query fetch nothing.

The daily ceiling of 2,500 Apple calls is shared with the listing-lookup queue above. Both lanes reserve from the same budget, which is why the counter can move when you have not refreshed anything.

Widening around a title. Refreshing a tracked app does not only collect the keywords you typed. It derives search terms from the app's own store title, taking whole title phrases first, then two-word windows, then single words, and asks Apple's suggestions about them, up to 8 terms and 80 queries. That is how ranking keywords surface without you having to guess them. If the daily budget runs out mid-job, the job stops widening and keeps what it collected.

Sources: packages/libraries/src/domain/app-catalog/aso-workstation.contract.ts, packages/libraries/src/domain/app-catalog/aso-discovery.ts, apps/backend/src/modules/aso-workstation/.

Why a profile's keyword list can be empty

A case file's ASO section is an invert: it lists the collected search snapshots that happen to contain that app. If nobody has ever collected a query that returns the app, the section is empty.

An empty invert means the app was not in the collected query set. It does not mean the app ranks for nothing. This distinction is worth holding onto, because the two look identical on screen if you do not know which one you are reading.

Public ad libraries

Large ad platforms publish transparency libraries: searchable archives of the ads an advertiser is currently running. PeekPanda stores observations from them, keyed to the platform and that platform's own archive id, so an ad is recorded once however many times it is seen.

What an observation holds:

  • The creative: the format (image, video, carousel, dynamic), the hook, body, title, description, call-to-action text, and the media URLs. Carousels keep their individual units.
  • The destination: where the ad sends people, classified as an App Store app, an official domain, another app store, or left explicitly unresolved. Each carries a confidence of verified or unresolved; a guess is never promoted to verified. Classifying an ad's destination is not catalogue coverage: only its iOS listing gets a case file.
  • The dates: when the ad started, when it ended if it has, and when PeekPanda discovered it.
  • The source URL, so you can go and check the library entry yourself.

What an observation does not hold is spend, budget, or impressions. Ad libraries do not publish them. The one performance figure that sometimes exists is a reach number the platform is legally required to disclose for the EU and UK, stored with the platform that reported it and the region it covers. See honest unknowns.

Sources: packages/libraries/src/domain/paid-ad-library/paid-ad-library.contract.ts, packages/db/src/schema/paid-ad-library.ts.

What your own tracked app contributes

Tracking an app in the ASO workstation adds nothing private to the shared catalogue. It changes which public queries get collected, not what is known about you.

Concretely:

  • Your tracked apps and your keyword lists are yours. Up to 25 tracked apps, up to 100 keywords each.
  • The search snapshots your refreshes produce are shared. A query you paid attention to is collected once and serves everyone.
  • Nothing about your app's internals, analytics, revenue or users enters PeekPanda. There is no SDK, no integration, and nothing to install. A tracked app is a store listing you have asked to watch.

The three intake lanes

An app gets into the catalogue three different ways, and the rules do not carry across. This matters because the bar an app cleared tells you what its presence means.

LaneHow it gets inThe bar
EstablishedOperator-run bulk importAt least 100 ratings and a store update inside a dated 12-month window
EmergingDiscovery from search terms you supplyReleased in the last 90 days and carrying at least 5 ratings
RequestedYou supply an App Store link or numeric app idNo rating floor at all

Established is a cohort, not a live pipeline. It was admitted by a bulk import pass against a recorded reference date, and its rule is a documented admission rule for that pass rather than a threshold enforced on every new app. The current catalogue is 81,870 iOS listings, of which 81,703 came in through an established import that used March 19, 2026 as its reference date; the remaining 167 came from an earlier seed. Not every listing in the catalogue met the established rule, and a future established run records its own cutoff rather than reusing that one.

Emerging exists precisely because a new app cannot clear the established bar. Discovery takes up to 12 search terms you type, reads up to 25 results for each, deduplicates them, and looks up at most 20 apps in detail per run. An app is admitted only when its release date is inside the last 90 days and it carries at least 5 ratings at the moment of lookup. Everything else is counted as rejected and nothing about it is stored. There is no open-ended crawl behind this; it runs on the terms you supplied.

Five ratings is a deliberately low bar. It admits an app for observation. It is not a claim that the app is doing well.

Requested admits one specific app with no rating floor, resolved from a numeric Apple id or an App Store URL. Google Play URLs are rejected rather than silently ignored.

An emerging or requested app is never held to the established threshold. The three lanes are separate on purpose, and a single canonical listing is kept per app however it arrived.

Freshness differs by lane too. Established listings carry the date of the import that admitted them, which may be considerably older than a chart snapshot from this morning. Always read the date on the fact, not the date of the page.

Sources: packages/libraries/src/domain/app-catalog/competitor-intake.contract.ts, apps/backend/src/modules/competitor-intake/, other/docs/engineering/plans/peekpanda-ios-scope-and-intake.md.

Organic social content

Organic results are a copied corpus of public social content, matched to apps by name.

A name match is a suggestion. It does not verify that an account belongs to the company behind the app, and PeekPanda never presents it as ownership. Read it as "an account with a similar name posts this", and confirm ownership yourself before acting on it.

What is not a source

To close the loop on where nothing comes from:

  • No commercial intelligence feed is called for any number in the product.
  • AppRank is a public website whose figures were read once to calibrate four revenue anchors. It is not an API PeekPanda calls, and nothing is imported from it. See how estimates are computed.
  • Apple's advertising Insights are not connected, so the 5–100 search popularity score advertisers see does not exist here.
  • No device panel, no SDK, no installed-app telemetry.