Owlmetry
MCP

Ads

Rank acquisition campaigns, ad groups, keywords, and ads by lifetime USD revenue via MCP tools.

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 keyword/ad leaves.

list-ad-campaigns

Rank campaigns by lifetime USD revenue from attributed users, joined to ad spend (where available) for ROAS. Aggregates app_users by attribution_source + campaign, joins each user's lifetime RevenueCat revenue, then LEFT JOINs ad_campaign_lifetime for spend / impressions / taps / installs synced from the network's Reports API (Apple Search Ads today). Returns user_count, paid_user_count (lifetime ever-paid), retained_user_count (currently on an auto-renewing paid subscription, excludes trials), total_revenue_usd, arpu, total_spend_usd, roas (revenue ÷ spend), start_date, status per campaign, sorted by revenue desc. Spend / ROAS are null when no Apple Search Ads integration is connected, no row in ad_campaign_lifetime matches yet, or the org reports in a non-USD currency — the response top-level carries total_spend_usd, ad_metrics_synced_at, and currency_warning (non-null currency code, e.g. "EUR", when at least one row's spend was reported in something other than USD).

Pass project_id for a single project, or team_id to aggregate the best-performing campaigns across every project in a team — each row then also carries a project_id so you can tell which project owns each campaign and use it on the project-scoped drill-downs (list-ad-groups, list-ad-leaves).

ParameterTypeRequiredDescription
project_idUUIDOne ofThe project ID. Mutually exclusive with team_id
team_idUUIDOne ofTeam ID — aggregates across every project in the team
attribution_sourcestringNoDefaults to apple_search_ads (only value populated today)
app_idUUIDNoScope to users acquired into a single app (project mode only; ignored when team_id is set)
limitnumberNoMax campaigns (1-500, default 100)

list-ad-groups

Rank ad groups within a campaign by lifetime USD revenue + spend (ROAS). Same response shape as list-ad-campaigns, one level deeper, joined against ad_adgroup_lifetime for ad-group-level spend / start_date / status. Each row carries total_spend_usd, roas, start_date, status alongside revenue / users / paid_user_count / retained_user_count / ARPU; the response top-level also exposes total_spend_usd, ad_metrics_synced_at, and currency_warning.

ParameterTypeRequiredDescription
project_idUUIDYesThe project ID
campaign_idstringYesNetwork-specific campaign ID returned by list-ad-campaigns
attribution_sourcestringNoDefaults to apple_search_ads
app_idUUIDNoScope to a single app
limitnumberNoMax ad groups (1-500, default 100)

list-ad-leaves

Within a single ad group, list keyword-level and ad-level revenue rankings side-by-side. Returns both keywords and ads arrays — 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.

ParameterTypeRequiredDescription
project_idUUIDYesThe project ID
campaign_idstringYesParent campaign ID
ad_group_idstringYesAd group ID returned by list-ad-groups
attribution_sourcestringNoDefaults to apple_search_ads
app_idUUIDNoScope to a single app
limitnumberNoMax leaves per side (1-500, default 100)

sync-ads

Trigger a manual refresh of advertising insights for one project. Fires both 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, filtered by adamId so each project only stores rows for its own apps). Admin-only. Both jobs also run on a daily cron — revenuecat_sync at 03:00 UTC, apple_ads_sync at 04:45 UTC.

ParameterTypeRequiredDescription
project_idUUIDYesThe project ID

Use this after onboarding a new RevenueCat integration or to force-refresh between cron runs. Use get-job on the returned job_run_id to monitor progress.

Ready to get started?

Connect your agent via MCP or CLI and start tracking.