
sensortowerR is an R client for Sensor Tower's API with a tidyverse-first workflow:
search apps and publishers, resolve IDs, fetch sales and active-user metrics, and chain everything with dplyr/tidyr.
remotes::install_github("econosopher/SensorTowerR")
Store your Sensor Tower API token as an environment variable:
usethis::edit_r_environ()
# SENSORTOWER_AUTH_TOKEN="YOUR_SECRET_TOKEN_HERE"
Restart your R session after updating .Renviron.
library(sensortowerR)
library(dplyr)
library(tidyr)
# 1) Find the app once, keep a canonical ID
app <- st_app_info("Royal Match") %>%
slice(1)
app_ids <- st_app_lookup(app$unified_app_id)
# 2) Pull active users (long format, ready for tidy pipelines)
active <- st_active_users(
os = "unified",
app_list = app$unified_app_id,
metrics = c("dau", "mau"),
date_range = list(start_date = "2025-01-01", end_date = "2025-12-31"),
countries = "US",
granularity = "monthly"
)
# 3) Pull sales for the same window
sales <- st_batch_metrics(
os = "unified",
app_list = app$unified_app_id,
metrics = c("revenue", "downloads"),
date_range = list(start_date = "2025-01-01", end_date = "2025-12-31"),
countries = "US",
granularity = "monthly"
)
# 4) Join and compute KPIs
active_wide <- active %>%
group_by(original_id, app_name, date, country, metric) %>%
summarise(value = sum(value, na.rm = TRUE), .groups = "drop") %>%
pivot_wider(names_from = metric, values_from = value)
sales_wide <- sales %>%
group_by(original_id, app_name, date, country, metric) %>%
summarise(value = sum(value, na.rm = TRUE), .groups = "drop") %>%
pivot_wider(names_from = metric, values_from = value)
kpis <- active_wide %>%
left_join(sales_wide, by = c("original_id", "app_name", "date", "country")) %>%
mutate(
rev_per_dau = if_else(!is.na(dau) & dau > 0, revenue / dau, NA_real_),
rev_per_mau = if_else(!is.na(mau) & mau > 0, revenue / mau, NA_real_)
)
The package is designed so users can think in terms of analysis, not raw endpoints.
| If you need... | Use... | Behavior |
|---|---|---|
| DAU/WAU/MAU for one or many apps | st_active_users() or st_batch_metrics() | Handles active-user retrieval and returns tidy long metrics for pipelines |
| Revenue/downloads for platform-specific reporting | st_sales_report() | Use os = "ios" or os = "android" |
| Revenue/downloads where IDs may vary (unified, iOS, Android) | st_metrics() | Resolves IDs and fetches by the requested os |
| Cross-app workflows with mixed metrics | st_batch_metrics() | Batches active users + sales and standardizes shape |
| Market rankings | st_top_charts(), st_top_publishers() | Top-and-trending style analysis by region/category |
Important behavior:
st_sales_report() is platform-specific and does not accept os = "unified".st_metrics() is the easiest way to request unified-style sales/download workflows.app <- st_app_info("Candy Crush Saga") %>%
slice(1)
ids <- st_app_lookup(app$unified_app_id)
ios_sales <- st_sales_report(
os = "ios",
ios_app_id = ids$ios_app_id,
countries = "US",
start_date = "2025-01-01",
end_date = "2025-01-31",
date_granularity = "daily"
)
portfolio <- st_publisher_portfolio(
publisher = "Supercell",
metrics = c("revenue", "downloads", "mau"),
start_date = "2023-01-01",
countries = "WW"
)
top_games <- st_top_charts(
measure = "revenue",
os = "unified",
category = 6014,
regions = "US",
time_range = "month"
)
st_gt_dashboard(top_games, title = "Top Games - US")
| Function | Purpose |
|---|---|
| st_app_info() | Search unified apps or publishers by term |
| st_app_lookup() | Resolve iOS/Android/unified IDs from any input ID |
| st_metrics() | Flexible single-app metric retrieval with ID resolution |
| st_sales_report() | Platform-specific sales/download estimates |
| st_unified_sales_report() | Unified aggregation across related regional SKUs |
| st_active_users() | Tidy DAU/WAU/MAU wrapper |
| st_batch_metrics() | Batch retrieval across apps and metrics |
| st_publisher_portfolio() | End-to-end publisher analysis |
| st_top_charts() | Top app rankings by metric |
| st_top_publishers() | Publisher rankings |
| st_category_rankings() | Official app store ranking pulls |
| st_gt_dashboard() | Formatted dashboard-style output |
| Data Type | Primary Function | Time Series | Coverage |
|---|---|---|---|
| Revenue/downloads (platform) | st_sales_report() | Yes | Country-level |
| Revenue/downloads (unified aggregation) | st_unified_sales_report() | Yes | Country-level |
| Revenue/downloads (ID-flexible) | st_metrics() | Yes | Country-level |
| DAU/WAU/MAU | st_active_users(), st_batch_metrics() | Yes | Country-level |
| Retention and demographics snapshots | st_app_enriched() | Snapshot | Primarily US/WW depending on metric |
st_cache_info()
save_id_cache()
load_id_cache()
st_clear_id_cache()
Cache location is CRAN-compliant via tools::R_user_dir("sensortowerR", "cache").
vignette("tidy-active-users", package = "sensortowerR")MIT (LICENSE file).
Any scripts or data that you put into this service are public.
Add the following code to your website.
For more information on customizing the embed code, read Embedding Snippets.