storebound/skills/apple-ads/SKILL.md

5.2 KiB

name description
apple-ads 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.