Ads
Rank acquisition campaigns, ad groups, keywords, and ads by lifetime USD revenue from the terminal.
Advertising Insights rank acquisition campaigns, ad groups, keywords, and ads by USD revenue from attributed users — and, when an Apple Search Ads integration is connected, by spend / ROAS alongside. Revenue aggregates app_users by attribution source and joins each user's lifetime RevenueCat revenue (refreshed daily and on every subscription webhook); spend / impressions / taps / installs come from Apple's Reports API into ad_campaign_lifetime + ad_adgroup_lifetime (refreshed daily by the apple_ads_sync job). Requires a RevenueCat integration for revenue data and Apple Search Ads attribution for human-readable names; the Apple Search Ads integration is also what unlocks spend numbers and start dates / status.
Trailing 12-month window. Both sides of the ROAS calculation are scoped to the same window: spend is summed from Apple's Reports API in 4×90-day chunks (Apple caps single requests at ~90 days), and revenue is filtered to users with app_users.first_seen_at inside that same window — so users acquired before the spend window's start don't inflate ROAS by contributing revenue against zero matchable spend. The window in days is echoed back as window_days on every ads response.
Drill from campaigns into ad groups, then into keywords + ads.
List campaigns
owlmetry ads campaigns (--project-id <id> | --team-id <id>) [--app-id <id>] [--source apple_search_ads] [--limit <n>]Lists campaigns ranked by total lifetime revenue desc. Pass --project-id for a single project, or --team-id to aggregate across every project in the team (the dashboard's "All projects" view) — each row then carries a project_id column so you can tell which project owns each campaign.
| Flag | Required | Description |
|---|---|---|
--project-id <id> | One of | Project UUID. Mutually exclusive with --team-id |
--team-id <id> | One of | Team UUID — aggregates across every project in the team |
--app-id <id> | No | Scope to users acquired into a single app (only with --project-id; ignored in team mode) |
--source <source> | No | Attribution network. Defaults to apple_search_ads (only value populated today) |
--limit <n> | No | Max rows (1–500, default 100) |
Drill into a campaign
owlmetry ads ad-groups <campaignId> --project-id <id> [--app-id <id>] [--source <source>] [--limit <n>]Lists ad groups within a campaign, ranked by revenue.
<campaignId> is the network-specific ID returned by ads campaigns (e.g. an Apple Search Ads campaign ID).
List keywords + ads in an ad group
owlmetry ads leaves <adGroupId> --campaign-id <id> --project-id <id> [--app-id <id>] [--source <source>] [--limit <n>]Returns two ranked tables side-by-side: keywords and ads. Apple Search Ads attributes a user to one or the other depending on whether the install came from a search keyword or an auto-driven ad placement.
| Flag | Required | Description |
|---|---|---|
<adGroupId> | Yes | Ad group ID (from ads ad-groups) |
--campaign-id <id> | Yes | Parent campaign ID |
--project-id <id> | Yes | Project UUID |
Trigger a manual sync
owlmetry ads sync --project-id <id>Fires revenuecat_sync (refreshes lifetime revenue per user) and apple_ads_sync (resolves any unresolved ASA IDs to readable names AND pulls campaign + ad-group spend / impressions / taps / installs from Apple's Reports API into ad_campaign_lifetime + ad_adgroup_lifetime) for the project. Admin-only.
Both jobs also run on a daily cron — revenuecat_sync at 03:00 UTC, apple_ads_sync at 04:45 UTC. Use this command to force-refresh between cron runs or right after onboarding a new RevenueCat or Apple Search Ads integration.
Output
Default table format renders ranked tables with columns: name (with [paused] / [deleted] status badge inline when applicable), users, Conv. (paid_user_count — anyone who has ever paid; lifetime fact), Retained (retained_user_count — users currently on an auto-renewing paid subscription, excludes trials), revenue, ARPU. Spend and ROAS columns appear automatically once at least one row carries a non-null total_spend_usd — ROAS is colored green / amber / red against the 1.0x and 0.5x thresholds. The summary line above the table adds total conversions / retained / spend / overall ROAS alongside total revenue, with a separate Spend synced timestamp; a yellow currency_warning line surfaces when the project's Apple Search Ads org reports in a non-USD currency (spend stays blank and ROAS unavailable until USD support lands).
Pass --format json for the raw API response (structured AdsCampaignsResponse, AdsAdGroupsResponse, AdsLeavesResponse) — every row carries total_spend_usd, roas, start_date, status, even when the table view doesn't render every field.
