A reusable Codex skill for Apple Ads campaign analysis, keyword/search term audits, and safe optimization workflows.
This repository is intentionally generic. It does not include private credentials, real campaign IDs, company names, audience assumptions, or product-specific keyword lists. Product strategy should come from the user's own product_profile.json.
- Tests Apple Ads API authentication.
- Fetches campaign, keyword, and search term performance.
- Inspects campaign and ad group structure.
- Identifies keyword efficiency, search term quality, negative keyword opportunities, and bid/status recommendations.
- Supports safe dry-run operations for bid changes, keyword pauses/enables, negative keywords, campaign status changes, and keyword plan uploads.
- Optionally compares Apple Ads totals with a separate Google Ads skill checkout.
python3 -m venv .venv
source .venv/bin/activate
pip install -r requirements.txt
cp .env.example .envEdit .env with your Apple Ads API credentials:
ASA_CLIENT_ID=SEARCHADS.CLIENT_ID
ASA_TEAM_ID=SEARCHADS.TEAM_ID
ASA_KEY_ID=KEY_ID
ASA_PRIVATE_KEY_PATH=/absolute/path/to/AuthKey_KEY_ID.p8
ASA_ORG_ID=Keep .env and private key files local. They are ignored by .gitignore.
python3 scripts/asa_auth.py
python3 scripts/asa_auth.py --list_orgsThe auth script verifies access without printing tokens, client secrets, or private key contents.
Copy the example profile and fill it with your app context:
cp product_profile.example.json product_profile.jsonUse it to describe the app, target markets, conversion goal, ideal search intents, negative intents, competitors, brand terms, and target CPA. The skill should not invent product strategy without this context.
python3 scripts/fetch_campaigns.py --date_range LAST_30_DAYS --format json
python3 scripts/fetch_keywords.py --date_range LAST_30_DAYS --campaign_id CAMPAIGN_ID --format json
python3 scripts/fetch_search_terms.py --date_range LAST_30_DAYS --campaign_id CAMPAIGN_ID --format json
python3 scripts/inspect_adgroups.py --campaign_id CAMPAIGN_IDSupported date presets: TODAY, YESTERDAY, LAST_3_DAYS, LAST_7_DAYS, LAST_14_DAYS, LAST_30_DAYS, LAST_90_DAYS.
All write-oriented scripts are dry-run by default. Add --apply only after reviewing the exact change.
python3 scripts/adjust_bids.py set --campaign_id CAMPAIGN_ID --keyword "keyword text" --bid 1.25
python3 scripts/manage_keywords.py pause --campaign_id CAMPAIGN_ID --keywords "keyword text"
python3 scripts/manage_negatives.py add --campaign_id CAMPAIGN_ID --keywords "irrelevant query"
python3 scripts/enable_campaign.py pause --campaign_id CAMPAIGN_IDApply example:
python3 scripts/adjust_bids.py set --campaign_id CAMPAIGN_ID --keyword "keyword text" --bid 1.25 --applyCopy and edit the sample keyword plan:
cp keyword_plan.example.json keyword_plan.json
python3 scripts/add_all_keywords.py --plan keyword_plan.json
python3 scripts/add_all_keywords.py --plan keyword_plan.json --applyThe plan supports campaign-level negative keywords and ad-group keyword batches.
Place this folder under your Codex skills directory or reference it from your agent workspace. The main skill instructions are in SKILL.md; the analysis sub-skill is in skills/ads-analyze/SKILL.md.
- Never commit
.env, private key files, raw reports, exports, logs, or account backups. - Use placeholders like
CAMPAIGN_ID,AD_GROUP_ID, andKEYWORD_IDin docs and examples. - Review dry-run output before adding
--apply. - Apple Ads data can lag by about 24 hours; avoid judging same-day changes as final.
MIT