Sensor Tower data through ordinary tibble pipelines. Search for apps, retain your analysis context, and fetch sales and audiences with one function.
library(sensortowerR)
library(dplyr)
st_apps("Clash of Clans", os = "unified") |>
filter(app_name == "Clash of Clans") |>
st_app() |>
st_metrics(
date_from = "2026-01-01",
date_to = "2026-03-31",
countries = c("US", "JP"),
metrics = c("revenue", "downloads", "mau"),
granularity = "monthly"
)Set SENSORTOWER_AUTH_TOKEN in your R environment, or
supply auth_token. The package never prints tokens. Both
|> and %>% work. Vector inputs require
an explicit platform; tibbles supply their own app_id and
os columns.
st_metrics(c("529479190", "553834731"), os = "ios",
date_from = "2026-01-01", date_to = "2026-01-31")Long output contains app_id, os,
country, date, metric,
value, unit and period. User
columns survive row expansion. Colliding input columns get an
.input suffix. Results are ungrouped tibbles, including
empty results.
Revenue defaults to USD dollars; downloads are counts.
shape = "wide" provides one value column per metric with
explicit unit and period columns. Missing values remain NA;
they are never filled with zero.
granularity controls sales. DAU, WAU and MAU retain
their native day, week and month windows. Dates label period starts.
Periods starting outside the requested range are excluded; partial
periods are not prorated. Unified and iOS audience sums are labeled
platform_users and device_users, respectively.
They are not deduplicated people. Audiences are never summed over
time.
Use countries = "WW" separately from country-specific
requests. Unified sales come directly from the unified endpoint,
including regional SKUs. The package does not infer identities from
names or merge related publishers.
| Task | Functions |
|---|---|
| Find apps and publishers | st_apps(), st_publishers() |
| Metadata and ID mapping | st_app(), st_publisher_apps() |
| Time series and market totals | st_metrics(), st_market_metrics() |
| Ranked estimates and store positions | st_rankings(), st_charts() |
| Specialist data | st_retention(), st_demographics(),
st_sessions(), st_ratings(),
st_reviews(), st_app_tags() |
| Filters and reference data | st_filter(), st_filter_create(),
st_filter_read(), st_fields(),
st_categories() |
| Advanced access and utilities | st_facets(), st_parse_url(),
st_build_url(), st_diagnostics(),
st_cache_info(), st_cache_clear() |
Metadata conversion is explicit:
st_app(data, target_os = "ios") expands all mapped iOS
SKUs; target_os = "unified" uses provider mappings.
Conversions retain input_app_id and input_os.
Demographics, legacy retention, ratings, reviews and tags require store
IDs; convert first when starting with unified IDs.
st_filter() constructs a local predicate without network
activity. st_filter_create() explicitly creates it on the
server. A failed creation raises an error and never manufactures an ID.
AND sends all fields in one request; OR creates one filter per field and
unions matching IDs. Multiple server writes are therefore possible for
an OR filter.
# This call creates server-side filters:
f <- st_filter(genre = "RPG", publisher = "Supercell", combine = "or") |>
st_filter_create()
st_apps(filter = f)Request and schema failures stop the pipeline by default.
errors = "partial" on data-first retrieval functions
returns identifiable failure rows with NA values,
status, error and endpoint, plus
a warning. A successful empty result is distinct from an error. Sales
and audience requests do not silently substitute one platform’s data for
a failed combined result.
Caching is off by default. cache = TRUE on
st_metrics() enables a session-only, credential-scoped
cache for 300 seconds (cache_ttl changes this). Partial
results and errors are not cached. Use st_cache_clear() to
clear entries.
Portfolio totals, YoY comparisons, charts, formatting and dashboards
now use recipes built from dplyr, ggplot2, scales and gt. See
vignette("recipes") and
inst/recipes/reports.R. See the
migration table for every v1.x export. This is a breaking 2.0.0
candidate; existing scripts need migration.
Run Rscript tools/check.R for offline tests, build and
package checks. Run
SENSORTOWER_RUN_LIVE=true Rscript tools/live-audit.R
separately for bounded read-only checks. Live results, unavailable
entitlements and empty responses are recorded separately in the
audit directory. Filter creation is tested offline. A successful
package check is not a claim that every API entitlement is
available.