storebound/skills/apple-ads/SKILL.md

66 lines
5.2 KiB
Markdown

---
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 <status | campaigns | report | bid | budget | pause>`. 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 <id>] [--adgroup <id>] [--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 <file>` 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 <id> --bid 1.25 [--campaign <id>] [--adgroup <id>] --dry`
- `storebound ads apple budget --campaign <id> --daily 50.00 --dry`
- `storebound ads apple pause --campaign <id> [--adgroup <id>] --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.