ring-intel
pubstoop.com · Ring Appstore desk
49 live listings
last scrape 2h ago

Methodology

ring-intel is a catalog observer. It records what Ring publishes and the BI Ring attaches to each listing. It does not estimate the rest of the market.

Source of truth

Every scrape requests https://ring.com/appstore/api/apps with User-Agent: ring-intel/0.1. The response body is stored as raw JSON with a SHA-256 hash. Each app is snapshotted on every successful scrape. There is no Ring SDK, Partner API, or GitHub listing mirror.

What the numbers are

clickUsers30d, accountLinkingUsers30d, and clickToLinkRate30d come from Ring's biMetrics object. They are Ring-reported business-intelligence figures for a trailing 30-day window (see windowEndDate on each app). ring-intel does not invent downloads, installs, active users, or revenue.

What we do not do

Listing fields

Name, studio, descriptions, features, images, billing, plans, trial eligibility, auth type, and partner identifiers are persisted as Ring returned them. Price labels are formatted from billing.plans[].amountInMinorUnits when the pricing model is paid; otherwise the listing is shown as Free.

Additional observed fields, backfilled from stored raw_json when a column is added:

Privacy declarations

The privacy matrix reads partner-submitted Contentful fields. They are labeled as CMS declarations, not as verified data-handling:

Permissions

Each listing includes a scopes array (name, isMandatory) and optional permissionsRoleId. The permission graph is the bipartite adjacency of live apps to those scope names. Catalog filters accept a scope name. A scope changelog event is written when the normalized scope set changes between scrapes.

Catalog facets

cameraType, deviceType, customerType, and partnerTags are stored as published string arrays and used as catalog filters. Values are not inferred beyond the payload.

Changelog

Publishers

Publishers are grouped by Ring partnerId. Several Appstore listings can share one partner organization and still use different public studio names.

Companion store listings

ring-intel joins public iOS, Android, and TV store listings to Ring catalog apps. A match is valid only if at least one of:

Titles are not fuzzy-matched. Shared studio homepages do not attach every badge to every SKU: AllScout's five Ring listings share one AllScout Ai binary; an extra PoolAgent listing is joined only to PoolAgent. Ring Cheer Chime is first-party and is never given a third-party companion. First-party Ring store badges that appear on partner homepages (com.ring / Ring Always Home) are ignored.

Collision rejects we keep explicit:

Seeva Online, Porchify, Beside Care, and Sojur stay unmatched unless a domain-joined listing appears. Minut may join when sellerUrl is minut.com, and is labeled a hardware companion, not Ring-specific. Video Wall is labeled TV (tvOS + Google TV), not a phone app.

iTunes Search/Lookup is free and requires no key. We prefer lookup-by-id once an id is known, and back off on HTTP 403. Observed fields: trackName, bundleId, trackId, sellerName, sellerUrl, version, currentVersionReleaseDate, averageUserRating, userRatingCount, trackViewUrl.

Google Play public HTML is parsed for an install range such as 500+, last update, developer name, and the details URL. The range is stored as a range. It is never treated as 500 installs, never turned into a rank, and never compared to Ring accountLinkingUsers30d.

Store-only SKUs seen on a known studio Play developer page (Garage Check, MomentReel, Flashbell, Dangerous Animal Alert, School Bus Home) are persisted as store-only, not in the Ring catalog. They have no invented Ring BI.

Cadence

Production scrape cadence is daily at 8am CT: cron 0 13 * * * hitting /api/cron/scrape. That job also does a cheap iTunes lookup-by-id for known companions when time remains. Play HTML and homepage badge discovery run on POST /api/cron/companions with the same CRON_SECRET. Hobby allows one cron per day; there is no 6-hour companion cron.