← All posts
Apple Ads reporting9 min read

How to Export Apple Ads Data to CSV, Power BI, and a Warehouse

Export Apple Ads data by CSV or API, then load spend, taps, impressions, campaigns, and keywords into Power BI, PostgreSQL, Redshift, or another BI tool.

Apple Ads reporting data flowing into CSV files, dashboards, and a data warehouse

You can export Apple Ads data manually as CSV or automate the export through Apple's Campaign Management API.

CSV is the fastest route for a one-off analysis. The API is the better foundation for Power BI, PostgreSQL, Redshift, Tableau, Qlik, or a recurring internal dashboard.

Apple renamed Apple Search Ads to Apple Ads in 2025. Many product screens, integrations, and search queries still use the old name, but the reporting architecture is the same.

The short answer

Choose the simplest extraction method that matches how often the data must refresh.

NeedRecommended methodWhat you maintain
One-off campaign reviewDownload a CSV from Apple AdsA local file and spreadsheet
Weekly analyst reportScheduled API extract to CSV or a databaseAuthentication, pagination, and refresh jobs
Power BI dashboardAPI extract to a stable table or JSON endpointA small server-side data pipeline
PostgreSQL reportingAPI extract plus an idempotent upsertSchema, keys, and late-data refreshes
Amazon Redshift reportingAPI extract to object storage, then COPY and MERGEStaging files and warehouse jobs
Keyword-level subscription ROASReporting data plus install attribution and revenue eventsThe join across spend, installs, and subscriptions

The last row is the important boundary. An Apple Ads export tells you what Apple delivered and spent. It does not, by itself, connect a keyword to a subscriber who paid or renewed later.

What Apple Ads data can you export?

Apple's Campaign Management API exposes reporting at several levels, including campaigns, ad groups, keywords, ads, and search terms. Depending on the endpoint and requested dimensions, the response can include:

  • Impressions and taps.
  • Spend and currency.
  • Installs and redownloads reported by Apple.
  • Campaign, ad group, keyword, and ad identifiers.
  • Names and status fields for reporting entities.
  • Date, country or region, and other available dimensions.

Keep both IDs and names. IDs are the durable join keys. Names are useful labels, but a campaign or ad group can be renamed after historical rows have already been loaded.

Apple's API metrics are aggregate reporting data. For a device-level install attribution flow, use AdServices separately. The Apple Ads API vs AdServices guide explains why most revenue pipelines need both.

Option 1: Download an Apple Ads CSV

For a manual export, create or open the relevant report in the Apple Ads dashboard, choose the date range and reporting level, then download the results as CSV.

Before using the file, record:

  • The account and organization.
  • The report time zone.
  • The selected date range.
  • The row level, such as campaign or keyword.
  • Any filters applied in the dashboard.
  • The currency represented by spend.

This context prevents a common spreadsheet problem: two exports look compatible but were produced with different filters, grains, currencies, or time zones.

CSV works well for an audit, a budget meeting, or an initial Power BI prototype. It becomes fragile when someone must repeat the download every morning or merge files from several accounts.

Option 2: Export with the Apple Ads API

Use the Campaign Management API when the export must run without a person opening the Apple dashboard.

A production extractor has four responsibilities:

  1. Authenticate with Apple's OAuth 2 flow.
  2. Request reports at a declared grain and date range.
  3. Follow pagination until every row is collected.
  4. Store raw and normalized results so retries are safe.

Apple access tokens expire after one hour, so the job should obtain or refresh a token at runtime. Keep the private key and client credentials in a server-side secret manager, not in a mobile app, spreadsheet, or shared Power BI file.

A campaign-level report request uses the reports endpoint and an organization context header:

curl --request POST \
  --url "https://api.searchads.apple.com/api/v5/reports/campaigns" \
  --header "Authorization: Bearer ACCESS_TOKEN" \
  --header "X-AP-Context: orgId=ORG_ID" \
  --header "Content-Type: application/json" \
  --data '{
    "startTime": "2026-08-01",
    "endTime": "2026-08-07",
    "granularity": "DAILY",
    "selector": {
      "pagination": { "offset": 0, "limit": 1000 }
    },
    "returnRowTotals": false,
    "returnGrandTotals": false
  }'

Treat this as a shape, not a credential setup guide. The exact selector, filters, grouping, and endpoint should match the report you need. Keyword-level reports use a campaign-specific keyword report endpoint.

Apple currently limits the span of individual reporting requests. Daily requests can cover at most 90 days, while hourly requests have a much shorter window. Split long imports into smaller intervals and preserve a checkpoint for each completed interval.

Apple also recommends retrying rate-limited or temporarily unavailable requests with increasing delays. Make a retry idempotent so it replaces the same logical rows rather than duplicating them.

Design the reporting table before loading data

Choose one grain per table. A useful keyword-day fact table might contain:

ColumnPurpose
report_dateThe date in the selected Apple report time zone
org_idApple Ads organization
campaign_idStable campaign join key
ad_group_idStable ad group join key
keyword_idKeyword identifier when available
keyword_bucketNamed keyword, Search Match, or another explicit fallback
country_or_regionGeographic reporting dimension
impressionsAggregate delivery metric
tapsAggregate tap metric
installsApple-reported install metric
spend_amountNumeric spend value
spend_currencyCurrency supplied with spend
source_updated_atWhen the source interval was last pulled

Do not silently convert a missing keyword ID to zero. Search Match and unavailable keyword cases should remain visible buckets, because they have different meanings from a named keyword.

Keep a raw-response table or object-storage copy as well. When Apple changes a field or your transformation has a bug, the raw payload lets you rebuild the normalized table without re-requesting every interval.

Connect Apple Ads to Power BI

Power BI can read CSV files, JSON, web APIs, and databases through Power Query. A direct call from a report file is possible in some configurations, but it is rarely the best production design for Apple Ads.

The safer pattern is:

Apple Ads API -> scheduled server-side extractor -> PostgreSQL, warehouse, or protected JSON/CSV endpoint -> Power BI

This keeps Apple's private key out of the .pbix file and gives one place to handle OAuth, retries, pagination, and schema changes.

For a quick prototype:

  1. Download the Apple Ads CSV.
  2. Import it with Power Query.
  3. Set explicit types for IDs, dates, spend, and currency.
  4. Create a folder-based query if several exports share the same schema.
  5. Replace the manual file source with a database or managed endpoint before relying on scheduled refreshes.

Avoid combining IDs as floating-point numbers. Large identifiers can lose precision in BI tools. Load them as text unless arithmetic is genuinely required.

Load Apple Ads data into PostgreSQL

For PostgreSQL, pull the API outside the database, validate the payload, then insert rows under a deterministic key. A simplified daily upsert looks like this:

INSERT INTO apple_ads_keyword_daily (
  report_date,
  org_id,
  campaign_id,
  ad_group_id,
  keyword_bucket,
  country_or_region,
  impressions,
  taps,
  installs,
  spend_amount,
  spend_currency,
  source_updated_at
)
VALUES (...)
ON CONFLICT (
  report_date,
  org_id,
  campaign_id,
  ad_group_id,
  keyword_bucket,
  country_or_region
)
DO UPDATE SET
  impressions = EXCLUDED.impressions,
  taps = EXCLUDED.taps,
  installs = EXCLUDED.installs,
  spend_amount = EXCLUDED.spend_amount,
  spend_currency = EXCLUDED.spend_currency,
  source_updated_at = EXCLUDED.source_updated_at;

The conflict key must match the actual report grain. If you add device class, placement, or another grouping, add it to the key or use a separate table.

Re-pull a rolling window instead of treating yesterday as permanently final. Attribution and reporting totals can settle after the first extract. A seven-day rolling refresh is a practical starting point, but the right interval depends on your reconciliation results.

Load Apple Ads data into Amazon Redshift

For Redshift, a common path is:

  1. Extract Apple Ads reports into compressed CSV or Parquet files.
  2. Write them to a date-partitioned object-storage location.
  3. Use Redshift COPY to load a staging table.
  4. Validate row counts, null keys, and spend currency.
  5. Use MERGE to update the reporting table.

Do not run a row-by-row insert for a large backfill. Bulk loading through COPY is designed for the warehouse use case and is easier to restart by partition.

Keep the source interval in the file path, for example report_date=2026-08-07/. That makes it easier to find, replace, and audit one day without rebuilding the full dataset.

What about Tableau, Qlik, Looker, or a JSON export?

The same architecture applies to other BI tools.

  • Tableau, Qlik, and Looker can query the normalized warehouse table.
  • A small internal service can expose protected JSON for lightweight tools.
  • A scheduled job can write CSV files to managed storage for teams that prefer file imports.
  • A transformation layer can create campaign, ad group, and keyword views from the same fact tables.

Choose the serving format after the extraction is reliable. Changing a Power BI model is much easier than recovering missing report intervals or compromised Apple credentials.

Add attribution before calling the result ROAS

Apple Ads reporting supplies the cost side of ROAS. It does not identify every subscriber in your product database.

To calculate keyword-level subscription ROAS, the complete chain is:

StageSource
Spend, taps, and impressionsApple Ads reporting API
Attributed installApple AdServices or an attribution provider
Trial, purchase, renewal, and refundRevenueCat, Superwall, StoreKit, or your backend
Cohort revenue and ROASA joined warehouse model or attribution product

Join with stable IDs and keep acquisition date separate from event date. A renewal recorded today may belong to a keyword that acquired the customer months ago.

The RevenueCat keyword ROAS guide and Superwall subscription attribution guide cover the two common subscription stacks.

A production checklist

Before trusting an automated Apple Ads export, verify:

  • OAuth credentials are stored only on the server.
  • Access tokens refresh without manual intervention.
  • Pagination stops only after all rows are received.
  • Report grain is part of the table key.
  • IDs are stored without numeric precision loss.
  • Currency and report time zone are explicit.
  • Search Match is not mislabeled as a broken keyword.
  • Recent dates are re-pulled to capture settled totals.
  • Raw responses are retained for replay and audit.
  • Dashboard totals reconcile to a known Apple Ads report for the same scope.
  • Subscription ROAS uses attributed revenue from the same acquisition cohort as spend.

If your real goal is the joined report rather than owning the export pipeline, connect Apple Ads to Postback to combine reporting data with attributed installs and downstream subscription events.

Sources

FAQ

Yes. You can download reporting data from the Apple Ads dashboard for one-off analysis. Record the report level, filters, date range, time zone, organization, and currency beside the file.

Power BI can call web sources, but a server-side extractor is usually safer for Apple Ads because it keeps the private key out of the report file and centralizes OAuth, pagination, retries, and schema handling.

Yes. Apple provides keyword-level reporting endpoints. Search Match and other cases without a selected keyword must remain separate from named-keyword rows.

Yes. Extract the API on a schedule, store a raw copy, and load a normalized table with deterministic keys. Use an upsert in PostgreSQL or a staging, COPY, and MERGE flow in Redshift.

Not by itself. The export supplies aggregate delivery and spend data. Subscription ROAS also needs AdServices install attribution and trial, purchase, renewal, or refund events joined to the same acquisition cohort.

You might also like

See all posts →