Skip to content

Apple Ads ​

Apple Ads (Apple Search Ads) is Apple's advertising platform for the App Store. App developers buy placements in the App Store's Search results, Today tab, "Suggested" list, and product pages — billed per tap or per install. Ads are rendered from the advertiser's App Store Connect listing; there is no separate creative upload.

This source uses the Apple Ads Campaign Management API v5 to ingest the structural data behind those ads — campaigns, ad groups, ads, and creatives.

URI format ​

appleads://?client_id=<client_id>&team_id=<team_id>&key_id=<key_id>&org_id=<org_id>&key_path=<path>

Or with a base64-encoded key:

appleads://?client_id=<client_id>&team_id=<team_id>&key_id=<key_id>&org_id=<org_id>&key_base64=<base64>

URI parameters ​

  • client_id (required) — Apple-issued API client identifier, format SEARCHADS.<uuid>.
  • team_id (required) — Apple-issued team identifier, format SEARCHADS.<uuid>. Usually the same value as client_id.
  • key_id (required) — Apple-issued key identifier for your uploaded public key (short UUID).
  • org_id (required) — Numeric organization/account ID. Comma-separated for multi-account ingestion (e.g. org_id=111,222,333).
  • key_path (one of) — Absolute filesystem path to the EC private key PEM file (P-256).
  • key_base64 (one of) — Base64-encoded contents of the EC private key PEM file. Use when no file system access is available.

Setup instructions ​

For Apple's official walkthrough of the same flow, see Implementing OAuth for the Apple Search Ads API.

1. Generate an EC key pair ​

Apple Ads uses ES256 (ECDSA P-256). Generate the pair locally — Apple never sees your private key.

bash
openssl ecparam -genkey -name prime256v1 -noout -out private-key.pem
openssl ec -in private-key.pem -pubout -out public-key.pem

2. Create an API user in Apple Ads ​

  1. Sign in to Apple Ads with an account that has admin permissions.
  2. Go to Account Settings → API.
  3. Invite a new API user and assign it a role (typically API Campaign Manager).
  4. Upload the public-key.pem file you generated.
  5. Apple will display:
    • Client ID (SEARCHADS.<uuid>)
    • Team ID (SEARCHADS.<uuid>)
    • Key ID (short UUID)

Copy these three values.

3. Find your Organization ID ​

Organization IDs are numeric and visible in:

  • Apple Ads UI → Settings → Overview.
  • The Apple Ads UI URL when browsing your account.

Tables ​

Entity tables ​

TablePKInc KeyInc StrategyDetails
campaigns[orgId, id]modificationTimemergeAll ad campaigns in the organization, including budget, status, countries/regions, and timeframe.
ad_groups[orgId, id]modificationTimemergeTargeting groups inside each campaign — bids, audience/device/geo targeting, and keyword-matching settings.
ads[orgId, id]modificationTimemergeIndividual ads within each ad group, linking a creative to its ad group and serving status.
creatives[orgId, id]modificationTimemergeCreative assets registered to the organization (custom product pages, text, media) that ads reference.

Report tables ​

Report tables return performance metrics (impressions, taps, installs, spend, etc.) from the Apple Search Ads Reporting API.

TablePKInc KeyInc StrategyDetails
campaign_reports[orgId, campaignId]modificationTimemergeCampaign-level performance metrics.
ad_group_reports[orgId, campaignId, adGroupId]modificationTimemergeAd group-level performance metrics.
ad_reports[orgId, campaignId, adId]modificationTimemergeAd-level performance metrics.

Report table names support an optional :granularity:groupBy suffix to control time breakdown and dimensional grouping:

  • Granularity — hourly, daily, weekly, or monthly. When set, date is added to the primary key.
  • GroupBy — one or more dimensions separated by commas. Each dimension is added to the primary key. campaign_reports and ad_group_reports accept any of countryOrRegion, ageRange, gender, deviceClass, adminArea, locality, countryCode. ad_reports is restricted to countryOrRegion only.

Granularity constraints (from Apple docs):

GranularityMin date rangeMax lookback
hourly—30 days
daily—90 days
weekly> 14 days24 months
monthly> 90 days (3 months)24 months

Example ​

Basic — ingest all campaigns ​

bash
ingestr ingest \
  --source-uri="appleads://?client_id=SEARCHADS.xxxx&team_id=SEARCHADS.xxxx&key_id=xxxx&org_id=11111111&key_path=/path/to/private-key.pem" \
  --source-table=campaigns \
  --dest-uri="duckdb:///tmp/apple_ads.duckdb" \
  --dest-table=main.campaigns

Incremental — only rows modified in the last day ​

bash
ingestr ingest \
  --source-uri="appleads://?client_id=...&team_id=...&key_id=...&org_id=...&key_path=..." \
  --source-table=ad_groups \
  --dest-uri="duckdb:///tmp/apple_ads.duckdb" \
  --dest-table=main.ad_groups \
  --interval-start=2026-04-21 \
  --interval-end=2026-04-22

ingestr will load ad groups whose modificationTime falls within the [interval-start, interval-end) window.

Multi-organization ​

bash
ingestr ingest \
  --source-uri="appleads://?client_id=...&team_id=...&key_id=...&org_id=11111111,98765432,11223344&key_path=..." \
  --source-table=campaigns \
  --dest-uri="duckdb:///tmp/apple_ads.duckdb" \
  --dest-table=main.campaigns

All campaigns from all three organizations land in a single table, distinguished by the orgId column.

Aggregated campaign report (no granularity, no groupBy) ​

bash
ingestr ingest \
  --source-uri="appleads://?client_id=...&team_id=...&key_id=...&org_id=...&key_path=..." \
  --source-table=campaign_reports \
  --dest-uri="duckdb:///tmp/apple_ads.duckdb" \
  --dest-table=main.campaign_reports

Daily campaign report by country ​

bash
ingestr ingest \
  --source-uri="appleads://?client_id=...&team_id=...&key_id=...&org_id=...&key_path=..." \
  --source-table='campaign_reports:daily:countryOrRegion' \
  --dest-uri="duckdb:///tmp/apple_ads.duckdb" \
  --dest-table=main.campaign_reports_daily_country

Aggregated report grouped by gender (no time breakdown) ​

bash
ingestr ingest \
  --source-uri="appleads://?client_id=...&team_id=...&key_id=...&org_id=...&key_path=..." \
  --source-table='campaign_reports::gender' \
  --dest-uri="duckdb:///tmp/apple_ads.duckdb" \
  --dest-table=main.campaign_reports_gender

Monthly metrics grouped by country and gender ​

bash
ingestr ingest \
  --source-uri="appleads://?client_id=...&team_id=...&key_id=...&org_id=...&key_path=..." \
  --source-table='campaign_reports:monthly:countryOrRegion,gender' \
  --dest-uri="duckdb:///tmp/apple_ads.duckdb" \
  --dest-table=main.campaign_reports_monthly_country_gender

Notes ​

  • The current API will be sunset on January 26, 2027. Apple has announced the Apple Ads Platform API as the replacement. A separate apple_ads_platform source may be added to cover that API when it becomes generally available.
  • Apple's id is not globally unique. It is only unique within an organization. Always join on the composite [orgId, id] when querying across orgs.