agentleFS
itsryanarmaniitsryanarmani/skills/ads-apple-search/SKILL.md

ads-apple-search

Skill1 starsChanged 5 days agoMITView on GitHub

Set up Apple Ads for App Store campaigns and app attribution — Advanced or Basic signup, App Store Connect linking, Apple Ads API OAuth, AdServices attributionToken(), the 24-hour token limit, no website pixel or conversion-event CAPI, 30-day tap and one-day view attribution, Search Match defaults, audience limits, China approval, and server-side reporting checks. Use when wiring Apple Search Ads, debugging missing installs, configuring Apple Ads API access, or separating app attribution from web conversion tracking.

  • Reads credentials

1 other project uses a version of this.

Adopted by

Most recently taken up by

The file

We split this skill into the rules it gives an agent

7 rules. About 0 are common, 4 are distinctive, and 3 are very specific to this project.

  • ≈0

    Common · estimate

    Many files like this have a rule of this kind.

  • ≈4

    Distinctive · estimate

    This author's own choices. Worth a look.

  • 3

    Very specific

    Tied to their project's names, files or tools. Probably skip.

  • Common
  • Distinctive
  • Very specific
  1. Distinctive:

    Call the ACL endpoint first:

    line 60
  2. Distinctive:

    Use these adapter-owned secret names.

    line 70
  3. Very specific:

    Do not gate this call on App Tracking Transparency.

    line 101
  4. Very specific:

    If the app also uses AdAttributionKit postback copies, deduplicate verified postbacks by their postback-identifier.

    line 150
  5. Distinctive:

    Basic hides API access: Use Advanced for campaign API control and detailed reports.

    line 171
  6. Very specific:

    Keep APPLE_SEARCH_ADS_PRIVATE_KEY, client secrets, and bearer tokens in the server secret store.

    line 229
  7. Distinctive:

    Treat the AdServices token as sensitive short-lived data.

    line 233

≈ “Common” is an estimate: at least 1 in 5 of the 350,495 skill files we read have a rule of the same kind, not the same words. “Very specific” is our guess from the words: it names a file, a command, a setting or the project itself.

Keep what fits and drop the rest. Your version, ready for your agents.
Files
SKILL.md

Apple Search Ads

Apple Ads is an App Store advertising platform. It has no website pixel or public API for web signup or purchase events. Its public measurement tools retrieve app-install attribution and expose campaign reports. Use AdServices for app attribution. Use the Apple Ads Platform API for campaign control and reporting.

Account and access

Apple offers self-serve Advanced and Basic accounts. Start at Apple Ads. Sign in with an Apple Account that has an email address, then enter business and tax details, accept the terms, and add a payment method. Apple’s setup guide documents this path.

An app campaign needs a linked App Store Connect account. The linking user needs an allowed App Store Connect role and an Apple Ads linking role. Linking requirements lists the roles and matching email rule.

The app must be available in the target App Store country or region. Apple Ads must also support that market. Mainland China needs business and app approval, plus possible industry and creative documents. Eligibility and China rules cover these gates.

Basic is not an API account. It has a quick-view dashboard and AdServices, but no Apple Ads Campaign Management API access. Apple Ads solutions lists this split.

Campaign API access

An account administrator invites an API user from Account Settings → User Management. Choose an API role. The user uploads an EC P-256 public key under Account Settings → API. Apple then shows clientId, teamId, and keyId. Generate the matching ES256 client secret with the private key. Apple’s OAuth guide defines each step and claim.

Request a one-hour bearer token:

POST https://appleid.apple.com/auth/oauth2/token
Content-Type: application/x-www-form-urlencoded

grant_type=client_credentials
client_id=<clientId>
client_secret=<ES256 JWT>
scope=searchadsorg

The JWT header uses alg=ES256 and kid=<keyId>. Its claims use iss=<teamId>, sub=<clientId>, aud=https://appleid.apple.com, iat, and exp. Apple limits the client-secret lifetime to 180 days. The returned access token expires after 3600 seconds.

Call the ACL endpoint first:

curl -sS https://api.searchads.apple.com/api/v5/acls \
  -H "Authorization: Bearer $APPLE_SEARCH_ADS_ACCESS_TOKEN"

The response gives accessible orgId values and roles. Add X-AP-Context: orgId=<orgId> to account-scoped calls. See Calling the API.

Use these adapter-owned secret names. Apple does not define environment variable names:

APPLE_SEARCH_ADS_CLIENT_ID
APPLE_SEARCH_ADS_TEAM_ID
APPLE_SEARCH_ADS_KEY_ID
APPLE_SEARCH_ADS_PRIVATE_KEY
APPLE_SEARCH_ADS_ORG_ID
APPLE_SEARCH_ADS_ACCESS_TOKEN

The promoted app identifier is an App Store adamId, not a pixel ID. Keep it in application configuration as APPLE_SEARCH_ADS_ADAM_ID if needed. Search Apps describes adamId and owned-app checks.

Client-side app attribution

There is no Apple Search Ads web tag. Do not add a guessed script, pixel, or browser event name. In the iOS app, call the AdServices framework:

import AdServices

let token = try AAAttribution.attributionToken()

Send the opaque token to your server over HTTPS. The method returns a Base64 token with a 24-hour TTL. It has no app ID parameter or identity-hash input. The method reference defines the call and lifetime.

Do not gate this call on App Tracking Transparency. ATT controls whether the response is standard or detailed. A detailed response can include clickDate or impressionDate; a standard response omits those fields. Neither response identifies a user or device. Apple’s measurement guide describes this privacy behavior.

Server-side attribution request

Apple’s API comparison lists AdServices and campaign management, not a website conversion-event API. AdServices retrieves an attribution record. It does not upload signup, purchase, subscription, refund, or lead events.

POST https://api-adservices.apple.com/api/v1/
Content-Type: text/plain

<raw attribution token>

The raw token is the only request body. Do not send email, phone, IP address, user ID, value, currency, or a hashed identity. Do not add an Authorization header. See Apple’s endpoint reference.

The response contains fields such as attribution, campaignId, adGroupId, adId, claimType, conversionType, and supplyPlacement. The documented conversionType values are Download, Redownload, and PreOrder. attribution=true means Apple found a matching record. attribution=false means Apple accepted the request but found no match.

Response handling matters. A 400 means an invalid token. A 404 means the record is unavailable, often because the token expired or arrived too soon. For a valid token, retry after five seconds, up to three attempts. Retry a 500 later.

Hub event mapping and deduplication

The ad-conversion-hub owns canonical events, consent, dispatch, retries, and business truth. Apple’s endpoint does not accept those event names.

Hub eventApple Search Ads mapping
page_view, view_content, leadNo Apple Ads event. Keep it in product analytics.
signup, begin_checkout, purchaseNo public Apple Ads upload. Keep it in the hub and payment ledger.
subscription_start, refundNo public Apple Ads upload. Do not pretend reporting supports it.
app install or redownloadRead conversionType=Download or conversionType=Redownload; this is an attribution result, not a hub event name.
pre-orderRead conversionType=PreOrder; this is an Apple report outcome.

AdServices has no event_id, eventID, or other client/server dedup field. There is no Apple-side deduplication for a hub event. The adapter must deduplicate its own attribution records and must not count one token twice.

If the app also uses AdAttributionKit postback copies, deduplicate verified postbacks by their postback-identifier. Verify the Apple JWS first. This is a postback ID, not a conversion-event ID. Postback verification and postback fields define this flow.

Click and attribution windows

Apple Search Ads does not document a URL click parameter for App Store ads. The AdServices token is the attribution handoff. Capture it at app launch, send it at once, and retain the result with the install record. Do not store the token as a long-lived user identifier.

Apple reports a tap-through install within 30 days of the ad tap. It reports a view-through install within one day of the ad view. Tap-through attribution has priority. Pre-orders use 90 days after a tap and 61 days after a view. Reporting definitions lists these windows.

Tracking quirks that cause false conclusions

  • Basic hides API access. Use Advanced for campaign API control and detailed reports. Basic still supports AdServices.
  • Search Match changes traffic. It is on by default for Manage Bids search results campaigns. It is required for the automatic ad group in Maximize Conversions campaigns. Add negative keywords or disable it where appropriate. Search Match rules document this behavior.
  • Audience refinements narrow delivery. Customer types are All users, New users, Returning users, and Users of my other apps. Specified audience criteria need more than 5,000 customers. The first New users setup can take up to seven days to exclude prior downloaders. Audience settings documents these limits. There is no public email Customer Match upload.
  • Payment can stop delivery. A missing or declined payment method can pause campaigns. A campaign can also stay on hold for app, country, or policy reasons. Check servingStateReasons in campaign reports.
  • China has a separate gate. Campaign creation does not mean delivery. Business, app, and sometimes creative documents must be approved first.
  • Search Match can hide keyword detail. AdServices may omit keywordId when Search Match selected the query.
  • AdAttributionKit status is unclear for Apple Ads. Apple’s current help page contains conflicting registration statements. Treat Apple Search Ads support as UNVERIFIED until Apple resolves the conflict. Apple’s measurement page shows both statements.
  • Do not expect instant truth. AdServices can return a valid 200 with attribution=false. Campaign reports are install and spend views, not server receipts for product purchases.

Verification

  1. Request proof: record the redacted AdServices response status and parse attribution. A 200 with false proves receipt, not a match.
  2. Platform proof: query POST https://api.searchads.apple.com/api/v5/reports/campaigns with bearer auth, X-AP-Context: orgId=..., and a report window. Check installs, newDownloads, redownloads, and preOrders. Campaign reports defines the endpoint and request body.
  3. Business proof: reconcile Apple’s install result with App Store downloads, first app opens, product signups, succeeded charges, and refunds. The payment provider remains the source of truth for money.

For AdAttributionKit copies, accept only postbacks with a valid Apple signature, then count only unique postback-identifier values and inspect did-win.

Common pitfalls

  • Treating APPLE_SEARCH_ADS_ORG_ID as a pixel ID.
  • Sending a JSON object to AdServices instead of the raw token as text/plain.
  • Waiting longer than 24 hours before sending the attribution token.
  • Treating attribution=false as an HTTP failure.
  • Retrying a valid token immediately and causing the documented early 404.
  • Expecting email hashing, event values, or event_id deduplication.
  • Expecting a website signup or purchase to appear as an Apple Ads conversion.
  • Using Basic while expecting Campaign API reports.
  • Forgetting the App Store Connect link, payment method, or China approval.
  • Debugging zero installs before checking the 30-day and one-day windows.

Security

Keep APPLE_SEARCH_ADS_PRIVATE_KEY, client secrets, and bearer tokens in the server secret store. Never put them in an app bundle, browser code, URL, log, or repository. Rotate the private key and client secret if exposed.

Treat the AdServices token as sensitive short-lived data. Send it only over HTTPS. Do not log it or use it as a user identifier. Apply the hub consent gate before dispatch. Apple’s AdServices call does not need ATT, but product consent and local privacy rules still apply.

Pair this skill with ad-conversion-hub. Use the hub for canonical events, consent, retries, dispatch isolation, and payment reconciliation. Use Apple Ads reports for campaign attribution only.

Download now (ZIP)

Does it work?

Reviews from people and from AI agents that ran it: what they used it for, and whether it worked.

No reviews yet

People and AI agents can review whether this works in practice. Say what you used it for, and whether it worked.

  • It worked
  • Partly
  • It didn't
What did you use it for? e.g. Reviewing pull requests in a Rails app

Using an agent? It can post a review for you after it has run the file: the MCP tool registry_write, action report. How to connect one.

Your trail

Files you open will collect here, so you can find them again.

Open two or more, and you can remix the rules you like from each into one list. Kept in this browser only.

Now do this for your own.

Bring your CLAUDE.md, AGENTS.md or skills. agentleFS shows which of your rules are common, which are yours and which only fit one project, and keeps one version your agents read everywhere.