Linking Apple Ads as a source
Let AI connect your sources for you
Skip the manual setup — run this in your project and the wizard auto-detects your databases and APIs and connects them to PostHog.

Contents
This source is currently in alpha. The interface and available tables may change.
The Apple Ads connector syncs your campaigns, ad groups, keywords, and daily performance reporting into PostHog, so you can analyze ad spend next to your product data. Apple Ads was called Apple Search Ads until Apple renamed it, and it now covers ads on both the App Store and Apple Maps.
PostHog reads version 1.0 of the Apple Ads Platform API.
Prerequisites
Neither PostHog nor Apple generates an API key for you. You generate a key pair yourself, an account administrator uploads the public half to Apple, and Apple then shows you the identifiers to paste into PostHog. Work through the four steps below before you link the source.
1. Create an API user
An Apple Ads account administrator signs in to Apple Ads, goes to Account Settings > User Management, and invites or edits a user with one of these roles:
- API Account Read Only – read access to the account. This is all PostHog needs.
- API Account Manager – read and write access. This works, but it grants more than PostHog uses.
Apple revokes API access if the user later moves to a non-API role, which makes syncs start to fail. Use a user whose role you don't expect to change.
2. Generate a key pair
The API user generates an EC P-256 key pair. OpenSSL is already installed on macOS and Linux:
Keep private-key.pem secret. If it leaks, generate a new pair and upload the new public key to Apple.
3. Upload the public key
The API user signs in to Apple Ads, goes to Account Settings > API, pastes the contents of public-key.pem into the Public Key field, and clicks Save.
Apple then shows three identifiers above that field. PostHog needs all three:
4. Find your ad account ID
The Platform API scopes every request to one ad account, so PostHog needs your ad account ID. This is not your organization ID, because one organization can hold several ad accounts.
Apple only serves this value from the API. Follow Apple's OAuth guide to sign a client secret with private-key.pem and exchange it for an access token, then call the Get User ACL endpoint:
Each entry in the response holds an adAccount.id. That value is your ad account ID.
Adding a data source
- In PostHog, go to the Sources tab of the data pipeline section.
- Click + New source and click Link next to this source.
- Enter your credentials (see Configuration below) and click Next.
- Select the tables you want to sync, choose a sync method and frequency, then click Import.
Once the syncs are complete, you can start querying this data in PostHog.
Sync modes
Each table can be synced in one of several modes, depending on what the source supports:
- Webhook (when available) – the source pushes changes to PostHog in real time. Fastest freshness, lowest ongoing cost, and the only mode that reliably captures updates and deletes.
- Incremental – only new or updated rows are synced on each run, using a cursor field (such as an
updated_attimestamp). Cheaper than a full refresh, but deletes aren't captured. - Append only – new rows are appended using a cursor field; existing rows are never updated. Ideal for immutable, append-only tables like event logs.
- Full refresh – the whole table is reloaded on every sync. Use it when a table has no reliable cursor or when you need deletions reflected.
See sync methods for a full explanation of how each mode works and how to choose between them.
The campaigns, ad_groups, keywords, and acls tables use full refresh, because Apple's query endpoints expose no updated-since cursor.
The three reporting tables sync incrementally by date. Each run re-reads a trailing window of recent days, because Apple restates recent reporting as attribution settles. Rows are merged away by primary key, so restatements replace earlier values instead of duplicating them.
Apple serves daily reporting for the last 90 days only. PostHog starts a couple of days inside that boundary, because Apple applies it in the ad account's own reporting time zone. If you set a report start date older than the window, PostHog starts from the oldest day Apple still serves rather than failing the sync. To build a longer history, connect the source and let it sync regularly — PostHog keeps the rows it has already imported after they age out of Apple's window.
Configuration
| Option | Description |
|---|---|
Ad account IDType: text Required: False | Read this from |
Client IDType: text Required: True | Apple shows this after you save the public key for your API client. |
Team IDType: text Required: True | Apple shows this next to the client ID. It often matches the client ID. |
Key IDType: text Required: True | Apple shows this next to the client ID. |
Private keyType: textarea Required: True | The unencrypted EC P-256 private key matching the public key you uploaded to Apple. |
Report start dateType: text Required: False | Earliest day to pull reporting for. Apple serves daily reporting for the last 90 days, so anything older is read from that day instead. |
Organization IDType: text Required: False | Only for sources still on Apple's Campaign Management API 5, which Apple stops serving on 26 January 2027. Leave this empty and enter an ad account ID instead. |
Supported tables
| Table | Description | Sync method | Incremental field | Primary key |
|---|---|---|---|---|
acls | Ad accounts the API credentials can read, with the organization and role names. | Full refresh | — | — |
campaigns | Campaigns in the account, with budget, serving status and countries or regions. | Full refresh | — | — |
ad_groups | Ad groups across every campaign in the account, with default bid and targeting. | Full refresh | — | — |
keywords | Targeting keywords across every ad group in the account, with match type and bid. | Full refresh | — | — |
campaign_report | Daily campaign performance: impressions, taps, installs, spend and derived rates. | Incremental, Full refresh | date | — |
ad_group_report | Daily ad group performance for every campaign in the account. | Incremental, Full refresh | date | — |
keyword_report | Daily keyword performance for every campaign in the account. | Incremental, Full refresh | date | — |
Troubleshooting
- 401 errors mean Apple rejected the access token. Check that the API client still exists under Account Settings > API, and that the private key in PostHog matches the public key uploaded there.
- 403 errors mean the API user can reach Apple but not this ad account. Check the user's role and the ad account ID.
- 404 errors mean Apple can't find the ad account. Re-read the ID from
adAccount.idrather than using your organization ID. - "The private key isn't a valid unencrypted EC (P-256) PEM" means the key was pasted in the wrong format. Paste the whole contents of
private-key.pem, including the-----BEGIN EC PRIVATE KEY-----and-----END EC PRIVATE KEY-----lines, and make sure the key isn't passphrase-protected. - Reporting tables are empty for older dates because of the 90-day daily reporting window described above. This is an Apple limit, not a sync failure.
If your sync is failing or data looks wrong, see the Data warehouse troubleshooting guide. If that doesn't help, contact support – we're happy to help.