Apple Search Ads API

Mobile App Advertising Software | Marin Software

How Does Apple Search Ads Work?

It is a user acquisition channel that connects app marketers with potential users in the App Store. When a search happens in the App Store, ads of certain apps appear at the top of the search page, given that they bid on the keyword and win the auction.

You are probably wondering what we mean by auction. When a keyword is searched for in the App Store, an auction is conducted amongst apps that want their ad to appear for the given keyword. These apps bid a certain amount to get their ads to appear, and the ad of the winning app is displayed at the top of the search results. 

Basic vs Advanced

Basic:

Apple Search Ads provides two versions for users – Basic and Advanced. The Basic version is suitable for smaller businesses with limited customization options. Users only need to provide the app, choose a country, set a CPI, and monthly budget. Apple’s algorithm will automatically match the ad to relevant searches, allowing for maximum growth with minimal commitment. The Basic version allows promotion for up to 50 apps with a maximum budget of $10,000 but doesn’t allow targeting specific keywords or setting up personalized campaigns.

Advanced:

The Advanced version of Apple Search Ads is recommended for dedicated app marketers who seek more customization options. With this version, users can create their campaign structure, set their own CPT, choose targeted keywords, and have full control over their budget. There is no limit to the number of apps or budget, enabling extensive campaigns across regions. Additionally, the Advanced version provides more detailed metrics for optimization and performance enhancement.

API Steps Summary:

The implementation of OAuth 2 for the Apple Search Ads Campaign Management API allows users to authenticate with credentials and obtain an access token for authenticated requests. This replaces the previous method of key and certificate authentication. The implementation process involves the following steps

  1. Inviting users with API permissions.
  2. Generating a private-public key pair.
  3. Uploading a public key.
  4. creating a client secret. and requesting an access token.
  5. Updating to OAuth 2 provides the advantage of managing access to accounts without requiring or sharing user login and password credentials.
  6. Users can continue to use key and certificate credentials until their certificates expire.

Step 1: Required by Client >> Invite Users

Account administrators invite users with API permissions using the following process:

  • From the Apple Search Ads UI, choose Sign In > Advanced and log in as an account administrator.
  • From the Users menu in the top-right corner, select the account to invite users to.
  • Choose Account Settings > User Management.
  • Click Invite Users to your Apple Search Ads organization.
  • In the User Details section, enter the user’s first name, last name, and Apple ID as Following.

    First Name: Sprighub

Last Name: Developers
Apple ID: developers@sprighub.com

Click Send Invite. The invited user receives an email with a secure code. The user signs into the secure Apple URL in the email and inputs the provided code, which activates the user’s account.


Step 2: Required by Developer >> Accept the Access inside the Email

  • The invited user receives an email with a secure code. The user signs into the secure Apple URL in the email and inputs the provided code, which activates the user’s account.

Note: The code is valid for 30 days. Be sure to activate your account before this invite expires

  • Go to Settings from the top right corner.
  • Enter the Public Key
  • The output looks like this

How to Generate Public and Private Keys Required for Client_id Generation

Private Key:

API users need to create a private key. If you’re using MacOS or a UNIX-like operating system, OpenSSL works natively. If you’re on a Windows platform, you need to download OpenSSL.

openssl ecparam -genkey -name prime256v1 -noout -out private-key.pem

Public Key:

Use the following command to extract a public key from your persisted private key:

openssl ec -in private-key.pem -pubout -out public-key.pem

Upload a Public Key:

Follow these steps to upload your public key:

  1. From the Search Ads UI, choose Account Settings > API. Paste the key created in the above section into the Public Key field.
  2. A group of credentials displays as a code block above the public key field. Use your clientId, teamId, and keyId to create a client secret.

Step 3: Create a Client Secret

To authenticate token requests to an authorization server, you need to create a client secret, which is a JSON web token (JWT) signed using your private key. This ensures that only you and the authorization server have access to the secret. The provided Python 3 script generates a client secret by generating or reading a private key in PEM format using elliptic curve cryptography (ECC). The script then defines the JWT headers and payload, encodes and signs the JWT with the private key, and saves the resulting client secret to a file. This client secret can then be used to obtain authorization tokens from the server.

Note: Make sure that you copy the private-public key pair into your working directory.

Python code to Generate Client_Secret

import os
import datetime as dt
from authlib.jose import jwt
from Crypto.PublicKey import ECC

private_key_file = "private-key.pem"
public_key_file = "public-key.pem"
client_id = "SEARCHADS.7b53d52d-b82d-49c6-9465-47a0db842819"
team_id = "SEARCHADS.7b53d52d-b82d-49c6-9465-47a0db842819"
key_id = "27013215-4ca3-4865-a047-4ab7f76b3d9c"
audience = "https://appleid.apple.com"
alg = "ES256"

# Create the private key if it doesn't already exist.
if os.path.isfile(private_key_file):
    with open(private_key_file, "rt") as file:
        private_key = ECC.import_key(file.read())
else:
    private_key = ECC.generate(curve='P-256')
    with open(private_key_file, 'wt') as file:
        file.write(private_key.export_key(format='PEM'))

# Extract and save the public key.
public_key = private_key.public_key()
if not os.path.isfile(public_key_file):
    with open(public_key_file, 'wt') as file:
        file.write(public_key.export_key(format='PEM'))

# Define the issue timestamp.
issued_at_timestamp = int(dt.datetime.utcnow().timestamp())
# Define the expiration timestamp, which may not exceed 180 days from the issue timestamp.
expiration_timestamp = issued_at_timestamp + 86400*180

# Define the JWT headers.
headers = dict()
headers['alg'] = alg
headers['kid'] = key_id

# Define the JWT payload.
payload = dict()
payload['sub'] = client_id
payload['aud'] = audience
payload['iat'] = issued_at_timestamp
payload['exp'] = expiration_timestamp
payload['iss'] = team_id

print(payload)
print(headers)


# Open the private key.
with open(private_key_file, 'rt') as file:
    private_key = ECC.import_key(file.read())


# Encode the JWT and sign it with the private key.
client_secret = jwt.encode(
    header=headers,
    payload=payload,
    key=private_key.export_key(format='PEM')
).decode('UTF-8')

# Save the client secret to a file.
with open('client_secret.txt', 'w') as output:
     output.write(client_secret)

Note: output client_secret will be generated


Step 4: client_id and client_secret can be used at any time to create an access token

import requests

url = 'https://appleid.apple.com/auth/oauth2/token'

headers = {
    'Host': 'appleid.apple.com',
    'Content-Type': 'application/x-www-form-urlencoded',
}

data = {
    'grant_type': 'client_credentials',
    'client_id': client_id,
    'client_secret': client_secret,
    'scope': 'searchadsorg'
}

response = requests.post(url, headers=headers, data=data)
response

The output will look like this:

'{"access_token":"eyJhbGciOiJkaXIiLCJlbmMiOiJBMjU2R0NNIiwia2lkIjpudWxsfQ..zVX0ZhIRD4Grya-M.GyZiBwrv9OcJ3PDR2Zr5CdIyeckIw-TFcX2iUIFe2ncdHiIG8z2fZSFb2ub9rMuhIw0QyB5QHCx7_BwqYoiSlctKuVdDWhJ3i6QeVUVTs7HaDOT2dBgp2mpB0rZzSi2Ujx4rVhGnxK2EJaXS0-T6-xeorqTwUczPABSDOiZ1EFqLSGEkNXheFEyNWKRaSX39jOm83UI25SHYFh12yYir0BXm-Z2oswA0bMSSD86itF_Yzna9x6u3DweQV1Ejng6QBofLck03R4d6n_EhtDIGe7E.mrUtZQKBlMqfnA49qleJ6w","token_type":"Bearer","expires_in":3600}'

Making First API Call to Apple search ads api

import requests

url = "https://api.searchads.apple.com/api/v4/acls"

headers = {
    "Authorization": "Bearer eyJhbGciOiJkaXIiLCJlbmMiOiJBMjU2R0NNIiwia2lkIjpudWxsfQ..zVX0ZhIRD4Grya-M.GyZiBwrv9OcJ3PDR2Zr5CdIyeckIw-TFcX2iUIFe2ncdHiIG8z2fZSFb2ub9rMuhIw0QyB5QHCx7_BwqYoiSlctKuVdDWhJ3i6QeVUVTs7HaDOT2dBgp2mpB0rZzSi2Ujx4rVhGnxK2EJaXS0-T6-xeorqTwUczPABSDOiZ1EFqLSGEkNXheFEyNWKRaSX39jOm83UI25SHYFh12yYir0BXm-Z2oswA0bMSSD86itF_Yzna9x6u3DweQV1Ejng6QBofLck03R4d6n_EhtDIGe7E.mrUtZQKBlMqfnA49qleJ6w"
}

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

# print the response status code and content
print(response.status_code)
print(response.content)

Output:

b'{"data":[{"orgName":"Pawan-Apple-Ads-Test-Account","orgId":7595140,"currency":"USD","timeZone":"UTC","paymentModel":null,"roleNames":["API Campaign Manager"],"parentOrgId":null,"displayName":"Pawan-Apple-Ads-Test-Account"}],"pagination":null,"error":null}'

Endpoints Working with

Official Documentation link: https://developer.apple.com/documentation/apple_search_ads/find_campaigns

Campaigns

Reports:

  • Campaign Level Reports

Endpoints: POST https://api.searchads.apple.com/api/v4/reports/campaigns

  • Get Ad Group Level Reports

Endpoints: POST https://api.searchads.apple.com/api/v4/reports/campaigns/{campaignId}/adgroups

  • Get Keyword Level Reports

Endpoint: POST https://api.searchads.apple.com/api/v4/reports/campaigns/{campaignId}/keywords

  • Get Keyword Level within an Ad Group Reports

Endpoints: POST https://api.searchads.apple.com/api/v4/reports/campaigns/{campaignId}/adgroups/{adgroupId}/keywords

Pawan Rai
DevOps Engineer at SprigHub
Cookie Value: