Apple Search Ads Integrations | Blue Frog Docs

Apple Search Ads Integrations

Integrations linking Apple Search Ads with analytics platforms, attribution providers, and mobile measurement partners.

Overview

Apple Search Ads provides a robust ecosystem for integrating with mobile measurement partners (MMPs), analytics platforms, and attribution frameworks. The platform's privacy-first approach, particularly with SKAdNetwork and the Search Ads Attribution API, enables conversion tracking while protecting user privacy in the post-iOS 14.5 era.

This guide covers all available integration options, from native Apple solutions to third-party partner integrations, helping you build a comprehensive measurement and optimization stack for your app campaigns.

Integration Capabilities

Native Apple Integrations

Apple Search Ads offers several native integration options that provide seamless data flow within the Apple ecosystem:

App Store Connect Integration

  • Automatic campaign performance data syncing
  • App Analytics integration for organic vs paid user comparison
  • Custom product page variant testing with Search Ads traffic
  • In-app event measurement and optimization
  • App clip campaign tracking

Search Ads API

  • Programmatic campaign management and reporting
  • Automated bid adjustments based on performance
  • Bulk campaign creation and editing
  • Custom reporting with granular metrics
  • Real-time performance monitoring

SKAdNetwork Framework

  • Privacy-preserving conversion attribution for iOS 14.5+
  • Conversion value schema (0-63) for in-app event mapping
  • Timer-based postback windows (0-24 hours, 24-48 hours, 48-72 hours)
  • Source app identifier for re-engagement campaigns
  • Lockout window randomization for privacy

Search Ads Attribution API

  • Client-side attribution token retrieval
  • Deterministic attribution for consented users
  • Keyword-level attribution data (when available)
  • Campaign and ad group granularity
  • Real-time install attribution

Platform Requirements

Access Levels

  • Basic reporting: Search Ads account with read access
  • Campaign management: Campaign manager role
  • API integration: Admin or API Account Manager role
  • App Analytics linking: App Store Connect admin or marketing role

Technical Prerequisites

  • iOS app published on App Store
  • Valid Apple Developer account
  • App Store Connect access
  • Xcode for SDK integration
  • Server infrastructure for API calls (if using Search Ads API)

Mobile Measurement Partner Integrations

Overview

Mobile measurement partners provide unified attribution, analytics, and fraud prevention across all your marketing channels, including Apple Search Ads.

Supported MMPs

AppsFlyer

  • Setup: Install AppsFlyer SDK, enable Search Ads attribution in dashboard
  • Attribution Method: Search Ads Attribution API + SKAdNetwork
  • Features:
    • Unified dashboard for all ad networks
    • Fraud protection and validation
    • Deep linking and deferred deep linking
    • Audience segmentation and retargeting
    • ROI and LTV measurement
    • Custom attribution windows
  • Data Available: Campaign, ad group, keyword (when user consented)
  • SKAdNetwork Support: Full conversion value management and postback handling
  • Cost: Included in AppsFlyer subscription tiers

Adjust

  • Setup: Integrate Adjust SDK, configure Search Ads in Adjust dashboard
  • Attribution Method: Search Ads Attribution API + SKAdNetwork
  • Features:
    • Real-time attribution and analytics
    • Fraud prevention suite
    • Audience builder for retargeting
    • Cohort analysis and retention tracking
    • Revenue and LTV analytics
    • Uninstall tracking
  • Data Available: Campaign, ad group, keyword, creative set
  • SKAdNetwork Support: Conversion value mapping and postback processing
  • Cost: Based on monthly attributed installs

Singular

  • Setup: Install Singular SDK, enable Search Ads in platform
  • Attribution Method: Search Ads Attribution API + SKAdNetwork
  • Features:
    • Marketing analytics and attribution
    • Cost aggregation across networks
    • ROI reporting and analysis
    • Fraud prevention
    • Creative reporting
    • ETL data pipeline
  • Data Available: Full Search Ads hierarchy data
  • SKAdNetwork Support: Advanced conversion value optimization
  • Cost: Based on attributed conversions

Branch

  • Setup: Integrate Branch SDK, configure Search Ads attribution
  • Attribution Method: Search Ads Attribution API + SKAdNetwork
  • Features:
    • Deep linking across platforms
    • Cross-platform attribution
    • Web-to-app attribution
    • Deferred deep linking
    • Journey and funnel analytics
    • People-based attribution
  • Data Available: Campaign and ad group data with keyword when available
  • SKAdNetwork Support: Conversion value schema management
  • Cost: Free tier available, paid plans for advanced features

Kochava

  • Setup: Install Kochava SDK, enable Apple Search Ads integration
  • Attribution Method: Search Ads Attribution API + SKAdNetwork
  • Features:
    • Multi-touch attribution
    • Fraud detection and prevention
    • Audience targeting
    • Deep linking
    • Cost and ROI analytics
    • Real-time reporting
  • Data Available: Campaign, ad group, keyword attribution
  • SKAdNetwork Support: Full postback handling and conversion value management
  • Cost: Based on monthly attributed installs

MMP Integration Setup

Step 1: SDK Integration

// Example: AppsFlyer SDK initialization
import AppsFlyerLib

func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
    AppsFlyerLib.shared().appsFlyerDevKey = "YOUR_DEV_KEY"
    AppsFlyerLib.shared().appleAppID = "YOUR_APPLE_APP_ID"

    // Enable Search Ads attribution
    AppsFlyerLib.shared().waitForATTUserAuthorization(timeoutInterval: 60)

    return true
}

Step 2: Configure SKAdNetwork

  • Add SKAdNetwork IDs to Info.plist
  • Configure conversion value schema in MMP dashboard
  • Map in-app events to conversion values (0-63 range)
  • Set up postback URL endpoint

Step 3: Enable Search Ads Attribution API

// Retrieve Search Ads attribution token
import AdServices

func requestAttributionData() {
    if #available(iOS 14.3, *) {
        if let token = try? AAAttribution.attributionToken() {
            // Send token to MMP or your server
            AppsFlyerLib.shared().attributionToken = token
        }
    }
}

Step 4: Configure Postbacks

  • Set up conversion event postback URLs
  • Map Search Ads events to MMP event taxonomy
  • Configure postback parameters (cost, revenue, custom dimensions)
  • Test postback delivery with test campaigns

Analytics Platform Integrations

Firebase Analytics

Integration Method: Via MMP or direct implementation

  • Setup: Install Firebase SDK, configure event tracking
  • Attribution Flow: MMP attributes install → Sends data to Firebase
  • Available Data: Campaign, ad group, source (limited by SKAdNetwork)
  • Use Cases:
    • Funnel analysis for Search Ads traffic
    • Comparing user behavior by acquisition source
    • LTV prediction models
    • A/B testing with Search Ads cohorts

Configuration:

// Firebase with Search Ads attribution
import FirebaseAnalytics

// Log acquisition events
Analytics.logEvent("ad_campaign_attribution", parameters: [
    "source": "apple_search_ads",
    "campaign": campaignName,
    "ad_group": adGroupName
])

Amplitude

Integration Method: Via MMP SDK integration or Events API

  • Setup: Install Amplitude SDK alongside MMP SDK
  • Attribution Flow: MMP attributes → Forwards to Amplitude
  • Available Data: User properties from Search Ads campaigns
  • Use Cases:
    • Behavioral cohort analysis
    • Product analytics by acquisition source
    • Retention analysis
    • User journey mapping

Configuration:

// Amplitude user properties from Search Ads
import Amplitude

let identify = AMPIdentify()
identify.set("acquisition_source", value: "apple_search_ads")
identify.set("campaign_name", value: campaignName)
identify.set("keyword", value: keyword) // When available
Amplitude.instance().identify(identify)

Mixpanel

Integration Method: Via MMP integration or Mixpanel SDK

  • Setup: Install Mixpanel SDK, configure attribution via MMP
  • Attribution Flow: MMP → Mixpanel via HTTP API or SDK
  • Available Data: Super properties with campaign attribution
  • Use Cases:
    • Funnel conversion analysis
    • Feature adoption by traffic source
    • Retention cohorts
    • Revenue analytics

Configuration:

// Mixpanel super properties for Search Ads users
import Mixpanel

Mixpanel.mainInstance().registerSuperProperties([
    "acquisition_channel": "apple_search_ads",
    "campaign": campaignName,
    "ad_group": adGroupName
])

Google Analytics for Firebase

Integration Method: Via Firebase integration

  • Setup: Enable Google Analytics in Firebase console
  • Attribution Flow: Firebase SDK → Google Analytics
  • Available Data: Limited by SKAdNetwork privacy requirements
  • Use Cases:
    • Cross-platform user journey tracking
    • E-commerce conversion tracking
    • Audience building for other channels

Attribution Framework Implementation

SKAdNetwork Setup

SKAdNetwork is Apple's privacy-preserving attribution framework, mandatory for iOS 14.5+ attribution.

Conversion Value Schema Design

Best practices for mapping in-app events to the 0-63 conversion value range:

Example Schema: E-commerce App

Values 0-9: Days since install (0=day 0, 9=day 9+)
Values 10-19: Purchase tiers (10=no purchase, 15=$1-50, 19=$100+)
Values 20-29: Session count (20=1 session, 29=10+ sessions)
Values 30-39: Reserved for future events

Example Schema: Gaming App

Values 0-19: Level progression (0=no progress, 19=level 20+)
Values 20-29: In-app purchase tiers
Values 30-39: Engagement score (sessions × time)
Values 40-63: Reserved

Implementation:

import StoreKit

// Update conversion value when key events occur
func updateConversionValue(for event: AppEvent) {
    var conversionValue: Int = 0

    switch event {
    case .levelCompleted(let level):
        conversionValue = min(level, 19)
    case .purchase(let amount):
        if amount >= 100 {
            conversionValue = 29
        } else if amount >= 50 {
            conversionValue = 25
        } else if amount > 0 {
            conversionValue = 20
        }
    }

    SKAdNetwork.updatePostbackConversionValue(conversionValue) { error in
        if let error = error {
            print("Error updating conversion value: \(error)")
        }
    }
}

Postback Handling:

  • Set up server endpoint to receive SKAdNetwork postbacks
  • Parse postback JSON for campaign ID and conversion value
  • Map conversion value back to meaningful events
  • Aggregate data for campaign optimization

Search Ads Attribution API

The Attribution API provides more granular attribution data for users who have granted permission.

Implementation:

import AdServices

class SearchAdsAttribution {
    static func requestAttribution() {
        if #available(iOS 14.3, *) {
            do {
                let token = try AAAttribution.attributionToken()

                // Send token to your server
                sendAttributionToken(token)
            } catch {
                print("Error getting attribution token: \(error)")
            }
        }
    }

    static func sendAttributionToken(_ token: String) {
        // POST to Apple's attribution endpoint
        let url = URL(string: "https://api-adservices.apple.com/api/v1/")!
        var request = URLRequest(url: url)
        request.httpMethod = "POST"
        request.setValue("application/json", forHTTPHeaderField: "Content-Type")

        let body = ["token": token]
        request.httpBody = try? JSONSerialization.data(withJSONObject: body)

        URLSession.shared.dataTask(with: request) { data, response, error in
            if let data = data {
                // Process attribution data
                if let attribution = try? JSONDecoder().decode(AttributionData.self, from: data) {
                    // Store or forward attribution data
                    print("Campaign: \(attribution.campaignId)")
                    print("Ad Group: \(attribution.adGroupId)")
                    print("Keyword: \(attribution.keyword ?? "not available")")
                }
            }
        }.resume()
    }
}

struct AttributionData: Codable {
    let campaignId: Int
    let adGroupId: Int
    let keyword: String?
    let attribution: Bool
}

Privacy Considerations:

  • Keyword data only available when user granted ATT permission
  • Campaign and ad group data available in limited form via SKAdNetwork
  • Always respect user privacy choices
  • Implement proper consent management

CRM and Marketing Automation Integrations

Salesforce Integration

Method: Via MMP offline conversion uploads or custom API integration

  • Use Case: Track high-value app users through sales funnel
  • Setup:
    1. Export Search Ads attribution data from MMP
    2. Match users by email or device ID (hashed)
    3. Upload as leads or contacts in Salesforce
    4. Track conversion to closed-won deals
  • Attribution Loop: Measure CAC to LTV for Search Ads channels

HubSpot Integration

Method: Via MMP webhooks or HubSpot API

  • Use Case: Marketing automation and lead nurturing for app users
  • Setup:
    1. Configure MMP to send install events to HubSpot
    2. Create contact properties for attribution data
    3. Set up workflows for Search Ads users
    4. Build segments for targeted campaigns
  • Benefits: Email nurturing, push notification targeting, multi-touch attribution

Custom CRM Integration

For custom CRM systems:

// Example: Sending attribution data to custom CRM
func sendToCRM(attributionData: AttributionData, userProfile: UserProfile) {
    let crmPayload: [String: Any] = [
        "user_id": userProfile.id,
        "email": userProfile.email,
        "acquisition_source": "apple_search_ads",
        "campaign_id": attributionData.campaignId,
        "ad_group_id": attributionData.adGroupId,
        "install_date": Date(),
        "attributed": attributionData.attribution
    ]

    // POST to your CRM API
    sendToAPI(endpoint: "https://your-crm.com/api/contacts", payload: crmPayload)
}

API Integration Patterns

Search Ads Campaign Management API

Authentication:

# Generate OAuth token
curl -X POST https://appleid.apple.com/auth/oauth2/token \
  -H "Content-Type: application/x-www-form-urlencoded" \
  -H "Authorization: Basic [base64_client_credentials]" \
  -d "grant_type=client_credentials&scope=searchadsorg"

Common API Operations:

Fetch Campaign Performance:

import requests

def get_campaign_metrics(access_token, org_id, campaign_id):
    url = f"https://api.searchads.apple.com/api/v4/campaigns/{campaign_id}"
    headers = {
        "Authorization": f"Bearer {access_token}",
        "X-AP-Context": f"orgId={org_id}"
    }

    response = requests.get(url, headers=headers)
    return response.json()

Automated Bid Management:

def update_keyword_bid(access_token, org_id, campaign_id, ad_group_id, keyword_id, new_bid):
    url = f"https://api.searchads.apple.com/api/v4/campaigns/{campaign_id}/adgroups/{ad_group_id}/targetingkeywords/{keyword_id}"

    headers = {
        "Authorization": f"Bearer {access_token}",
        "X-AP-Context": f"orgId={org_id}",
        "Content-Type": "application/json"
    }

    payload = {
        "bidAmount": {
            "amount": str(new_bid),
            "currency": "USD"
        }
    }

    response = requests.put(url, json=payload, headers=headers)
    return response.json()

Bulk Reporting:

def get_campaign_report(access_token, org_id, start_date, end_date):
    url = f"https://api.searchads.apple.com/api/v4/reports/campaigns"

    headers = {
        "Authorization": f"Bearer {access_token}",
        "X-AP-Context": f"orgId={org_id}",
        "Content-Type": "application/json"
    }

    payload = {
        "startTime": start_date,
        "endTime": end_date,
        "selector": {
            "orderBy": [{"field": "localSpend", "sortOrder": "DESCENDING"}],
            "pagination": {"offset": 0, "limit": 1000}
        },
        "groupBy": ["countryOrRegion"],
        "timeZone": "UTC",
        "returnRowTotals": True,
        "returnRecordsWithNoMetrics": False
    }

    response = requests.post(url, json=payload, headers=headers)
    return response.json()

Data Export and Warehouse Integration

Export Options

Search Ads Reporting API

  • Format: JSON via REST API
  • Frequency: Real-time to daily aggregation
  • Granularity: Campaign, ad group, keyword, search term
  • Metrics: Impressions, taps, installs, spend, average CPA, TTR, conversion rate
  • Retention: Up to 12 months via API

MMP Data Exports

  • Format: CSV, Parquet, JSON
  • Delivery: S3, Google Cloud Storage, SFTP, HTTP endpoint
  • Frequency: Hourly, daily, or real-time streaming
  • Scope: Raw install data, aggregated reports, cohort analysis
  • Use Cases: Data warehouse loading, BI tool integration

Data Warehouse Integration

BigQuery Integration Example:

from google.cloud import bigquery
import requests

def load_search_ads_to_bigquery(access_token, org_id, project_id, dataset_id):
    # Fetch data from Search Ads API
    campaigns = get_all_campaigns(access_token, org_id)

    # Transform to BigQuery schema
    rows_to_insert = []
    for campaign in campaigns:
        rows_to_insert.append({
            "campaign_id": campaign["id"],
            "campaign_name": campaign["name"],
            "impressions": campaign["impressions"],
            "taps": campaign["taps"],
            "installs": campaign["installs"],
            "spend": campaign["spend"],
            "date": campaign["date"]
        })

    # Load to BigQuery
    client = bigquery.Client(project=project_id)
    table_id = f"{project_id}.{dataset_id}.search_ads_campaigns"

    errors = client.insert_rows_json(table_id, rows_to_insert)
    if errors:
        print(f"Errors: {errors}")
    else:
        print("Data loaded successfully")

Snowflake Integration:

  • Use Search Ads API to export to S3
  • Configure Snowpipe for automatic ingestion
  • Transform data with dbt or Snowflake SQL
  • Join with other marketing data sources

Redshift Integration:

  • Export Search Ads data to S3 via scheduled scripts
  • Use COPY command to load into Redshift
  • Create materialized views for common queries
  • Join with app event data from MMPs

Common Integration Issues

Issue 1: Missing Attribution Data

Symptoms:

  • Installs showing as organic when they should be attributed to Search Ads
  • Keyword data not appearing in MMP dashboard

Causes:

  • Search Ads Attribution API not implemented
  • SKAdNetwork not properly configured
  • User denied ATT permission
  • Attribution window mismatch

Solutions:

  • Implement both SKAdNetwork and Attribution API
  • Verify Info.plist includes Apple's SKAdNetwork ID
  • Check MMP integration is properly configured
  • Review attribution window settings (default is 30 days)

Issue 2: Conversion Value Not Updating

Symptoms:

  • All SKAdNetwork postbacks showing conversion value of 0
  • Events firing but not reflected in postback

Causes:

  • Conversion value not being updated in code
  • Events firing after 24-hour lockout window
  • Incorrect conversion value schema

Solutions:

// Ensure conversion value updates occur early
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
    // Initialize early
    DispatchQueue.main.asyncAfter(deadline: .now() + 2.0) {
        // Update conversion value after app is stable
        SKAdNetwork.updatePostbackConversionValue(10) // Base value for install
    }
    return true
}

// Update for key events
func onPurchaseComplete(amount: Double) {
    let value = calculateConversionValue(for: amount)
    SKAdNetwork.updatePostbackConversionValue(value)
}

Issue 3: API Authentication Failures

Symptoms:

  • 401 Unauthorized errors from Search Ads API
  • Token expires unexpectedly

Causes:

  • Invalid client credentials
  • Expired OAuth token
  • Incorrect org ID in headers
  • Insufficient permissions

Solutions:

  • Verify client ID and secret in Apple Search Ads UI
  • Implement token refresh logic (tokens expire after 1 hour)
  • Confirm user has API Account Manager role
  • Check X-AP-Context header includes correct orgId

Issue 4: Data Discrepancies

Symptoms:

  • Install counts differ between Search Ads and MMP
  • Revenue numbers don't match between platforms

Causes:

  • Attribution window differences
  • Time zone mismatches
  • Currency conversion
  • Different event definitions

Solutions:

  • Align attribution windows across platforms
  • Use UTC for all date comparisons
  • Store revenue in single currency before aggregation
  • Document event definitions and ensure consistency
  • Accept 5-10% variance as normal due to attribution methodology

Support and Resources

When to Contact Support

Apple Search Ads Support:

  • Campaign approval issues
  • Billing discrepancies
  • API access problems
  • Account access issues
  • Contact: Search Ads support in dashboard or Apple Business Chat

MMP Support:

  • Attribution discrepancies > 10%
  • SKAdNetwork postback issues
  • SDK integration problems
  • Data export failures
  • Contact: Via partner support portals

App Store Connect Support:

  • App Analytics integration issues
  • Custom product page problems
  • In-app event configuration
  • Contact: App Store Connect support

Additional Resources

Backlog & Opportunities

  • Explore advanced SKAdNetwork conversion value mapping strategies for multi-event optimization
  • Evaluate custom product pages for Search Ads traffic to improve conversion rates
  • Implement server-to-server attribution validation for fraud prevention
  • Test fine conversion value updates to maximize data granularity within 6-bit limit
  • Build automated bid management using machine learning on Search Ads API data
  • Create unified attribution dashboard combining SKAdNetwork and deterministic data
  • Implement cross-promotion workflows using shared attribution insights across app portfolio
// SYS.FOOTER