Claude
Skills
Sign in
โ† Back

Apple Search Ads

Included with Lifetime
$97 forever

Create, optimize, and scale Apple Search Ads campaigns with API automation, attribution integration, and bid strategy recommendations.

Ads & Marketing

What this skill does


# Apple Search Ads ๐ŸŽ

Complete toolkit for Apple Search Ads: Campaign Management API v5, attribution integration (AdServices + SKAdNetwork), bid optimization, and strategic recommendations.

## What's New in v1.0.0

- Full Campaign Management API v5 coverage
- iOS app integration (AdServices framework)
- SKAdNetwork 4.0 support
- Automated reporting scripts
- Bid optimization strategies
- Multi-country campaign patterns

## Contents

1. [Setup](#setup)
2. [When to Use](#when-to-use)
3. [Architecture](#architecture)
4. [API Essentials](#api-essentials)
5. [Campaign Structure](#campaign-structure)
6. [Keywords & Bidding](#keywords--bidding)
7. [Attribution Integration](#attribution-integration)
8. [Reports & Analytics](#reports--analytics)
9. [Strategy Playbook](#strategy-playbook)
10. [Scripts & Automation](#scripts--automation)
11. [Common Traps](#common-traps)

## Setup

On first use, read `setup.md` for integration guidelines.

## When to Use

User needs to run Apple Search Ads for iOS apps. Agent handles campaign creation, bid optimization, attribution tracking, performance analysis, and strategic recommendations.

## Architecture

Memory lives in `~/apple-search-ads/`. See `memory-template.md` for structure.

```
~/apple-search-ads/
โ”œโ”€โ”€ memory.md          # Active campaigns, preferences, learnings
โ”œโ”€โ”€ credentials.md     # OAuth config (NEVER commit real secrets)
โ”œโ”€โ”€ campaigns/         # Campaign-specific notes and performance
โ”‚   โ””โ”€โ”€ {app-id}/
โ”œโ”€โ”€ reports/           # Generated reports
โ””โ”€โ”€ scripts/           # Custom automation
```

## Quick Reference

| Topic | File |
|-------|------|
| Setup process | `setup.md` |
| Memory template | `memory-template.md` |
| API endpoints | `api-reference.md` |
| iOS integration | `ios-integration.md` |
| Strategy guide | `strategy.md` |
| Script library | `scripts.md` |

## API Essentials

### Authentication (OAuth 2.0)

Apple Ads API uses OAuth with client credentials. Generate credentials at:
https://app.searchads.apple.com/cm/app/settings/apicertificates

```bash
# 1. Generate client secret (JWT signed with private key)
# Header
{
  "alg": "ES256",
  "kid": "{KEY_ID}"
}
# Payload
{
  "sub": "{CLIENT_ID}",
  "aud": "https://appleid.apple.com",
  "iat": {CURRENT_TIMESTAMP},
  "exp": {TIMESTAMP_+180_DAYS},
  "iss": "{TEAM_ID}"
}

# 2. Exchange for access token
curl -X POST "https://appleid.apple.com/auth/oauth2/token" \
  -H "Content-Type: application/x-www-form-urlencoded" \
  -d "grant_type=client_credentials" \
  -d "client_id={CLIENT_ID}" \
  -d "client_secret={CLIENT_SECRET}" \
  -d "scope=searchadsorg"

# Response contains access_token (valid 1 hour)
```

### Base URL & Headers

```
Base URL: https://api.searchads.apple.com/api/v5
Headers:
  Authorization: Bearer {ACCESS_TOKEN}
  X-AP-Context: orgId={ORG_ID}
  Content-Type: application/json
```

### Core Endpoints

| Resource | Method | Endpoint |
|----------|--------|----------|
| **Apps** | | |
| Search apps | POST | `/search/apps` |
| App eligibility | GET | `/apps/{adamId}/eligibilities` |
| **Campaigns** | | |
| List campaigns | GET | `/campaigns` |
| Create campaign | POST | `/campaigns` |
| Update campaign | PUT | `/campaigns/{id}` |
| Delete campaign | DELETE | `/campaigns/{id}` |
| **Ad Groups** | | |
| List ad groups | GET | `/campaigns/{id}/adgroups` |
| Create ad group | POST | `/campaigns/{id}/adgroups` |
| **Keywords** | | |
| List keywords | GET | `/campaigns/{cId}/adgroups/{agId}/targetingkeywords` |
| Add keywords | POST | `/campaigns/{cId}/adgroups/{agId}/targetingkeywords/bulk` |
| **Reports** | | |
| Campaign report | POST | `/reports/campaigns` |
| Ad group report | POST | `/reports/campaigns/{id}/adgroups` |
| Keyword report | POST | `/reports/campaigns/{cId}/adgroups/{agId}/keywords` |
| Search term report | POST | `/reports/campaigns/{cId}/searchterms` |
| Impression share | POST | `/reports/campaigns/{id}/impressionshare` |

## Campaign Structure

### Hierarchy

```
Organization (orgId)
โ””โ”€โ”€ Campaign (Search Results / Search Tab / Today Tab)
    โ”œโ”€โ”€ Budget & Schedule
    โ”œโ”€โ”€ Countries/Regions
    โ””โ”€โ”€ Ad Groups
        โ”œโ”€โ”€ Keywords (targeting + negative)
        โ”œโ”€โ”€ Audience (age, gender, device, etc.)
        โ”œโ”€โ”€ Creatives (default or Custom Product Pages)
        โ””โ”€โ”€ Bid settings
```

### Campaign Types

| Type | Placement | Best For |
|------|-----------|----------|
| **Search Results** | Top of search results | High-intent users, brand defense |
| **Search Tab** | Suggested apps before search | Discovery, broad reach |
| **Today Tab** | Today tab featured | Brand awareness, launches |

### Campaign Object

```json
{
  "name": "MyApp - US - Brand",
  "adamId": 123456789,
  "countriesOrRegions": ["US"],
  "budgetAmount": {"amount": "1000", "currency": "USD"},
  "dailyBudgetAmount": {"amount": "50", "currency": "USD"},
  "supplySources": ["APPSTORE_SEARCH_RESULTS"],
  "billingEvent": "TAPS",
  "status": "ENABLED",
  "startTime": "2026-01-01T00:00:00.000",
  "endTime": null
}
```

### Ad Group Object

```json
{
  "name": "Brand Keywords",
  "campaignId": 123456,
  "defaultBidAmount": {"amount": "1.50", "currency": "USD"},
  "cpaGoal": {"amount": "5.00", "currency": "USD"},
  "startTime": "2026-01-01T00:00:00.000",
  "targetingDimensions": {
    "age": {"included": [{"minAge": 18}]},
    "gender": {"included": ["M", "F"]},
    "deviceClass": {"included": ["IPHONE", "IPAD"]},
    "daypart": {"userTime": {"included": [0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23]}},
    "adminArea": null,
    "locality": null,
    "appDownloaders": {"included": [], "excluded": []}
  },
  "automatedKeywordsOptIn": false,
  "status": "ENABLED"
}
```

## Keywords & Bidding

### Match Types

| Type | Behavior | Use Case |
|------|----------|----------|
| **Exact** | Query = keyword exactly | Brand terms, proven converters |
| **Broad** | Synonyms, related terms | Discovery, expansion |
| **Search Match** | Auto-matched by Apple | New apps, keyword research |

### Keyword Object

```json
{
  "text": "meditation app",
  "matchType": "EXACT",
  "bidAmount": {"amount": "2.00", "currency": "USD"},
  "status": "ACTIVE"
}
```

### Bid Strategy Rules

1. **Brand keywords** โ†’ Bid high (defend your brand)
2. **Competitor keywords** โ†’ Test carefully, monitor CPA
3. **Generic keywords** โ†’ Start low, increase for winners
4. **Discovery (Search Match)** โ†’ Low bids, mine for keywords
5. **Negative keywords** โ†’ Essential to reduce waste

### Bid Optimization Loop

```
Week 1: Set baseline bids (industry avg or $1-2)
        โ†“
Week 2: Review search term report
        - High converts, low bid โ†’ raise bid 20-30%
        - Low converts, high spend โ†’ lower bid or pause
        - Irrelevant terms โ†’ add as negative
        โ†“
Week 3+: Repeat. Target CPA within 20% of goal.
```

## Attribution Integration

### AdServices Framework (iOS 14.3+)

Modern attribution without user tracking. Integrates directly in iOS app.

```swift
import AdServices

func trackAttribution() async {
    do {
        // 1. Get attribution token from device
        let token = try AAAttribution.attributionToken()
        
        // 2. Send to Apple's attribution API
        var request = URLRequest(url: URL(string: "https://api-adservices.apple.com/api/v1/")!)
        request.httpMethod = "POST"
        request.setValue("text/plain", forHTTPHeaderField: "Content-Type")
        request.httpBody = token.data(using: .utf8)
        
        let (data, _) = try await URLSession.shared.data(for: request)
        let attribution = try JSONDecoder().decode(Attribution.self, from: data)
        
        // 3. attribution contains: campaignId, adGroupId, keywordId, etc.
        // Send to your analytics backend
        
    } catch {
        // Not from Apple Search Ads or error
    }
}

struct Attribution: Codable {
    let attribution: Bool
    let orgId: Int?
    let campaignId: Int?
    let adGroupId: Int?
    let keywordId: Int?
    let creativeSetId: Int?
    let conversionType: String?

Related in Ads & Marketing