Skip to content

Latest commit

 

History

History
322 lines (251 loc) · 10.7 KB

File metadata and controls

322 lines (251 loc) · 10.7 KB

Apple Ads Operator Playbooks

Practical Apple Ads workflows for safe setup, read-only checks, reporting, and guarded mutations

Use these playbooks when you are operating Apple Ads from asc in a terminal, CI job, or agent run. The goal is to start read-only, confirm the ad-account context, and only mutate resources after the target IDs and payload files are reviewed.

The primary examples use the direct Platform API v1 resource commands under asc ads with --ad-account. The deprecated Campaign Management API v5 tree is isolated in the migration and legacy sections below.

Setup and Credential Safety

Apple Ads credentials are separate from App Store Connect API credentials. asc auth login does not configure asc ads.

Create a named Apple Ads profile and store the default ad account when you know it:

asc ads auth login \
  --name "Marketing" \
  --client-id "SEARCHADS_CLIENT_ID" \
  --team-id "SEARCHADS_TEAM_ID" \
  --key-id "KEY_ID" \
  --private-key "$HOME/.asc/apple-ads-private-key.pem" \
  --ad-account "987654" \
  --network

For CI, prefer secrets and environment variables over checked-in config:

export ASC_ADS_CLIENT_ID="SEARCHADS_CLIENT_ID"
export ASC_ADS_TEAM_ID="SEARCHADS_TEAM_ID"
export ASC_ADS_KEY_ID="KEY_ID"
export ASC_ADS_PRIVATE_KEY_PATH="$HOME/.asc/apple-ads-private-key.pem"
export ASC_ADS_AD_ACCOUNT_ID="987654"
export ASC_ADS_BYPASS_KEYCHAIN=1

asc ads apps search --ad-account "$ASC_ADS_AD_ACCOUNT_ID" --query "Example" --output json

Use a read-only API command for CI validation so the run resolves the exported ASC_ADS_* credentials and org context instead of only listing stored profiles.

Use ASC_ADS_PRIVATE_KEY_B64 when your CI secret store handles single-line values more reliably than PEM blocks. Keep ASC_ADS_ACCESS_TOKEN for cases where another trusted system already minted a short-lived token.

Platform API v1 migration

For new automation, start with the Apple Ads Platform API v1 command tree:

asc ads me view --output json
asc ads acls list --output json
asc ads apps search --ad-account "987654" --query "Example" --output json

The legacy Campaign Management API v5 commands under asc ads v5 still run in 4.4.0 and print a deprecation warning on stderr. Apple retires v5 on January 26, 2027. A v5 command keeps its existing --org context; a v1 command uses the separate --ad-account context. Do not pass an organization ID where a v1 ad account ID is required, or assume that the two IDs identify the same thing.

V1 query, report, and mutation bodies use the Platform API schemas. Put the appropriate v1 object in --file; the CLI does not convert a v5 selector, reporting request, numeric ID, or response envelope. V1 report pagination stays in the request JSON, so do not add the legacy --paginate flag to a v1 report command:

asc ads reports apps campaigns \
  --ad-account "987654" \
  --file report.json \
  --output json

Platform v1 exposes one negative-keywords resource for both campaign and ad group scope. Move the scope into the v1 query or mutation body rather than looking for separate campaign-negative-keywords and ad-group-negative-keywords commands. The v5 asc ads v5 reports preset helper remains a warning-producing compatibility path; replace it with an explicit v1 report leaf and reviewed request file.

Seven v5 leaves have no one-command v1 replacement in 4.4.0: product-page countries, product-page devices, targeting-keyword bulk delete, campaign negative-keyword bulk delete, ad-group negative-keyword bulk delete, and impression-share report list and view. Related v1 commands are not drop-in replacements for those contracts. In particular, geo search is not the v5 country/device mapping, insights impression-share is not the custom report list/view API, and v1 has no bulk-delete operation.

For raw calls, keep asc ads v5 api request for v5 paths and its --org context. It remains runnable with a warning and is not rewritten. Use asc ads api request --path v1/... --ad-account ... for a raw v1 call.

Account Access Inspection

Start outside an ad-account context. These commands do not require --ad-account:

asc ads acls list --output json

Use the ACL response to confirm the ad account ID, then pin it explicitly for the rest of the session:

export ASC_ADS_AD_ACCOUNT_ID="987654"
asc ads apps search --ad-account "$ASC_ADS_AD_ACCOUNT_ID" --query "Example" --limit 1 --output json

When operating multiple Apple Ads accounts, avoid relying on the ambient default. Pass both profile and ad account:

asc ads apps search \
  --ads-profile "Marketing" \
  --ad-account "987654" \
  --query "Example" \
  --output json

Safe Read-Only Smoke Test

Use this sequence before an automation run or after rotating credentials:

ASC_BYPASS_KEYCHAIN=1 asc ads acls list --output json
ASC_BYPASS_KEYCHAIN=1 asc ads apps search --ad-account "987654" --query "Example" --limit 1 --output json

Expected result: every command exits successfully, and the app search returns either a result envelope or an empty result. Treat auth failures, missing account errors, or unexpected account names as stop conditions.

When using stored Ads profiles, add profile validation before the API smoke test:

asc ads auth status --validate --output json

Campaign and Ad Group Inventory

Query campaigns first, then inspect ad groups under one confirmed campaign ID:

asc ads campaigns find \
  --ad-account "987654" \
  --file campaign-query.json \
  --output json

asc ads ad-groups find \
  --ad-account "987654" \
  --file ad-group-query.json \
  --output json

For a full v1 query, keep pagination in the request body:

asc ads campaigns find --ad-account "987654" --file campaign-query.json --output json
asc ads ad-groups find --ad-account "987654" --file ad-group-query.json --output json

Do not use report payloads as inventory replacements. Reports answer performance questions; list and find endpoints answer "what exists right now?" questions.

Report Workflow

Use Platform API v1 for new report automation. Its body shape differs from v5:

{
  "pagination": {"offset": 0, "pageSize": 20},
  "filters": [
    {"field": "campaignId", "operator": "EQUALS", "value": ["444555666"]}
  ],
  "groupBy": ["countryOrRegion"],
  "timeRange": {
    "start": "2025-01-01",
    "end": "2025-01-31",
    "timeZone": "ORTZ",
    "granularity": "DAILY"
  }
}
asc ads reports apps campaigns \
  --ad-account "987654" \
  --file platform-report.json \
  --output json

The v1 report response keeps Apple's raw result and pagination fields. Change offset and pageSize in the file to fetch another page. Run asc ads reports apps campaigns --help for body and option guidance; report entities do not all accept the same groupBy values.

Legacy v5 report compatibility

The request below is the deprecated v5 shape. Keep it only while existing automation migrates:

{
  "startTime": "2026-05-01",
  "endTime": "2026-05-31",
  "returnRowTotals": true,
  "returnGrandTotals": true,
  "selector": {
    "pagination": {
      "offset": 0,
      "limit": 100
    },
    "orderBy": [
      {
        "field": "impressions",
        "sortOrder": "DESCENDING"
      }
    ]
  }
}

Run the campaign report with an explicit org and output format:

asc ads v5 reports campaigns \
  --org "123456" \
  --file reporting-request.json \
  --output json

For ad-group, keyword, search-term, or ad-level reports, first verify the parent campaign ID with asc ads v5 campaigns list. Report pagination lives inside the Apple Ads request body, so update the file's selector pagination rather than adding --paginate.

Raw API Safety

Use asc ads api request for Platform API v1 debugging, newly added Apple fields, or support captures. Prefer first-class commands for routine work.

Read-only raw request:

asc ads api request \
  --method POST \
  --path v1/campaigns/query \
  --ad-account "987654" \
  --file campaign-query.json \
  --output json

Raw v1 requests only accept Platform API v1 paths or https://api.ads.apple.com/v1/... URLs. DELETE requests and risky mutation payloads require --confirm; multipart asset upload must use asc ads assets upload.

For legacy troubleshooting only, keep asc ads v5 api request with its v5 path and --org context:

asc ads v5 api request \
  --method POST \
  --path v5/campaigns/find \
  --org "123456" \
  --file selector.json \
  --output json

Raw requests only accept Apple Ads v5 paths or Apple Ads API URLs. DELETE requests require --confirm; do not pass it until the command line includes the exact target path you intend to delete.

Mutation Safety Checklist

Before running create, update, delete, or bulk commands:

  1. Run the matching --help command and confirm required flags.
  2. Resolve account access with asc ads acls list --output json.
  3. Run a read-only resource check: asc ads apps search --ad-account "987654" --query "Example" --limit 1 --output json.
  4. Pass --ads-profile and --ad-account explicitly when more than one account is possible.
  5. Store request bodies in reviewed JSON files; avoid shell-escaped inline JSON.
  6. Create paused or clearly named test resources when validating workflow shape.
  7. Print or log the target IDs before using --confirm.
  8. Prefer deleting temporary parent campaigns only after confirming Apple allows the cleanup.

Example guarded delete:

asc ads campaigns view --ad-account "987654" --campaign "campaign-id" --output json
asc ads campaigns delete --ad-account "987654" --campaign "campaign-id" --confirm

Troubleshooting Auth and Source Precedence

Use the auth doctor first:

asc ads auth doctor --output json
asc ads auth status --verbose --output json

Common fixes:

  • Missing ad account: pass --ad-account, export ASC_ADS_AD_ACCOUNT_ID, or store --ad-account during login.
  • Wrong profile: pass --ads-profile "Marketing" or export ASC_ADS_PROFILE.
  • Keychain prompts in CI: export ASC_ADS_BYPASS_KEYCHAIN=1.
  • Mixed sources: set ASC_ADS_STRICT_AUTH=1 to fail when both profile and env token/key sources are present.
  • Token-only runs: ASC_ADS_ACCESS_TOKEN still needs --ad-account, ASC_ADS_AD_ACCOUNT_ID, or a stored profile account for scoped v1 commands.

When debugging API responses, use an explicit output format and redact tokens, client IDs, team IDs, key IDs, org IDs, and account names before sharing logs.