--- name: apple-ads description: Read Apple Ads (formerly Apple Search Ads) results for a mobile app or game and make small, owner-approved bid, daily budget and pause changes - API user setup (role, key pair, client id / team id / key id), ad account check, campaign list, spend / taps / installs / CPA reports per campaign or keyword with CSV export, and keyword bid, campaign daily budget and pause changes that always show old -> new and ask first. Use when the user asks how their Apple Ads / Search Ads campaigns perform, what an install costs, wants a spend report or CSV, or wants to raise or lower a bid or budget or pause a campaign. --- # Apple Ads: reports and small changes CLI: `storebound ads apple `. storebound uses the **Apple Ads Platform API** (`api.ads.apple.com/v1`). It replaces the Campaign Management API v5, which Apple turns off on January 26, 2027. Both use the same API credentials, so a key you made for v5 keeps working. Reports and lists are read-only. Bid, budget and pause spend or stop money: they are the owner's decisions. ## Setup (once, by the owner, in the Apple Ads web UI) 1. An account admin invites the API user: ads.apple.com > Sign In > Advanced > Account Settings > User Management > Invite Users, with an API role on the ad account: - `API Account Read Only`: reports and lists only. Enough for `status`, `campaigns`, `report`. - `API Account Manager` (or `Limited Access: API Read & Write`): needed for `bid`, `budget`, `pause`. Start read-only unless the owner wants to change bids from the terminal. 2. The API user makes a key pair on their own machine (the private key never leaves it): `openssl ecparam -genkey -name prime256v1 -noout -out apple-ads-private-key.pem` `openssl ec -in apple-ads-private-key.pem -pubout -out apple-ads-public-key.pem` 3. Apple Ads > Account Settings > API: paste the public key, Save. Apple shows `clientId`, `teamId`, `keyId`. 4. The owner puts them into `.storebound/credentials.json` (gitignored) or the environment. Never paste them in chat: - `APPLE_ADS_CLIENT_ID` (`SEARCHADS.…`), `APPLE_ADS_TEAM_ID` (`SEARCHADS.…`), `APPLE_ADS_KEY_ID` - `APPLE_ADS_PRIVATE_KEY`: path to the private key PEM (or the PEM itself) - `APPLE_ADS_ACCOUNT_ID`: the ad account id. Leave it empty at first; step 5 lists the ids. 5. `storebound ads apple status`: checks the token, lists the ad accounts with your roles (`*` = the one used), the account's currency, time zone and status, and whether the role can write. Set `APPLE_ADS_ACCOUNT_ID` to the App Store account (product feature `APPSTORE_APP_MANUAL`) and run it again. 6. Set `apple.appId` in `storebound.config.ts` (the App Store app id, the number in the app's store URL). Lists and reports then show only this app's campaigns (`--all` for every app in the account). storebound signs a short-lived client secret per run and keeps the access token in memory only. ## Read - `storebound ads apple campaigns [--all] [--json]`: id, name, status, display status, daily budget, bid strategy, countries, adamId (`*` = this app). - `storebound ads apple report [--days 7 | --start 2026-10-01 --end 2026-10-07] [--by campaign|keyword] [--campaign ] [--adgroup ] [--csv store/ads.csv] [--json]` - Window: `--days N` ends yesterday (UTC; today is still incomplete), or `--start` / `--end` inclusive. - Columns: spend (account currency), impressions, taps, installs (tap + view-through), TTR (taps / impressions), CR (installs / taps), CPA (spend / installs, `n/a` with 0 installs), average CPT (spend / taps), and a TOTAL line. - `--by keyword` lists every keyword of the chosen campaigns (narrow with `--campaign`, `--adgroup`). - `--csv ` writes the rows (rates as fractions, empty CPA cell with 0 installs); `--dry` writes nothing. - Only rows with activity are returned. Apple's numbers can still change for a day or two. - Read the report with the owner: high spend with 0 installs, a CPA above what a user is worth (compare with revenue or LTV), keywords with many impressions and a low TTR (weak relevance or creative). ## Change (owner only, in a terminal) - `storebound ads apple bid --keyword --bid 1.25 [--campaign ] [--adgroup ] --dry` - `storebound ads apple budget --campaign --daily 50.00 --dry` - `storebound ads apple pause --campaign [--adgroup ] --dry` Each reads the current value first and prints `old -> new` with the change in percent, in the account currency. Show the dry run to the owner. Only the owner runs it without `--dry`; it asks `[y/N]` before the change. Without a terminal it changes nothing (unless `--yes`), and under the desktop app or MCP it is always refused. An agent never adds `--yes` on its own. Keyword bids do nothing in Maximize Conversions campaigns: the command refuses those. To resume a paused campaign, use the Apple Ads web UI. ## Out of scope - Creating or deleting campaigns, ad groups, keywords, ads, creatives, custom product pages, budget orders: use the Apple Ads web UI. - Search Ads attribution in the app (AdServices framework / Apple Ads attribution API), SKAdNetwork, MMPs. - Apple Maps (brand) campaigns. - Any automatic bidding rules: storebound makes one change at a time, and only when the owner says so.