Creating ASO Projects
Overview
ASO (App Store Optimization) projects track apps and their performance across different app stores with multi-market support. There are two types:
- ASO_ANDROID - Track apps in Google Play Store
- ASO_APPLE - Track apps in Apple App Store
๐ All Endpoints Now Implemented
All endpoints described below are now fully implemented and available via the REST API. You can also manage everything via the Django admin interface at /admin/.
Multi-Market Support
Each ASO project can track ONE app across MULTIPLE country-language markets simultaneously. Each market has its own keywords and competitor apps.
Example: Track WhatsApp across three markets: - ๐บ๐ธ US/EN - US English market with US competitors - ๐ฉ๐ช DE/DE - German market with German competitors - ๐ฎ๐ณ IN/EN - Indian English market with Indian competitors
Unified Single-Endpoint Setup
Creating a complete ASO project is now ONE request:
1. Create Base Project (POST /api/workspaces/{workspace_id}/projects/)
โ
2. POST to ASO Config Endpoint with COMPLETE data:
- App info (new or existing)
- Markets to track (list of country-language pairs)
- Keywords to track (across all markets)
- Competitor apps to monitor (across all markets)
- Internal notes
โ
3. DONE! Everything created atomically
The endpoint automatically: - โ Creates or gets the app (by package_id/bundle_id or UUID) - โ Creates market localizations (country-language pairs) - โ Links keywords to each market - โ Links competitor ACLs - โ Creates the ASO configuration with all M2M relationships
All in one transaction!
Step 1: Create Base Project
The foundation - all ASO projects start here.
Endpoint: POST /api/workspaces/{workspace_id}/projects/
Request:
Required Fields:
- name (string) - Project name (e.g., "WhatsApp Android Tracker")
- type (string) - Either ASO_ANDROID or ASO_APPLE
Response (201 Created):
{
"id": "550e8400-e29b-41d4-a716-446655440000",
"name": "WhatsApp Android Tracker",
"workspace_id": "660e8400-e29b-41d4-a716-446655440001",
"type": "ASO_ANDROID",
"user_access": [],
"aso_android_config": null,
"aso_apple_config": null,
"created_at": "2024-10-28T12:00:00Z",
"updated_at": "2024-10-28T12:00:00Z"
}
Note: aso_android_config is null because we haven't configured it yet.
Step 2: Create ASO Configuration (Complete Project Setup)
Link everything together in ONE request - app, multiple markets, keywords per market, competitors per market.
Understanding the Project Structure
Before creating your ASO config, understand the data hierarchy:
Your ASO Project (tracks ONE app)
โ
โโ App (e.g., WhatsApp)
โ โโ Country-Languages (all available markets for this app)
โ โโ us/en (WhatsApp in US, English)
โ โโ de/de (WhatsApp in Germany, German)
โ โโ jp/ja (WhatsApp in Japan, Japanese)
โ
โโ Tracked Markets (markets you're actively monitoring)
โ โโ Market 1: us/en
โ โ โโ Keywords (tracked for THIS market)
โ โ โ โโ "messaging app", "secure messenger"
โ โ โโ Competitors (OTHER apps' markets in us/en)
โ โ โโ Telegram us/en
โ โ โโ Signal us/en
โ โ โโ Discord us/en
โ โ
โ โโ Market 2: de/de
โ โ โโ Keywords (tracked for THIS market)
โ โ โ โโ "Messaging-App", "sicherer Messenger"
โ โ โโ Competitors (OTHER apps' markets in de/de)
โ โ โโ Telegram de/de
โ โ โโ Signal de/de
โ โ
โ โโ Market 3: jp/ja
โ โโ Keywords (tracked for THIS market)
โ โ โโ "ใกใใปใผใธใณใฐใขใใช"
โ โโ Competitors (OTHER apps' markets in jp/ja)
โ โโ LINE jp/ja
โ
โโ Notes (internal documentation)
Key Points: - Your app can have many country-language pairs available - You can monitor MULTIPLE markets in ONE project - Each market has its own keywords and competitors - Competitors must be OTHER apps' markets in the SAME country/language - This lets you compare performance against competitors in each geography+language - All markets in one atomic transaction
For Android Projects
Endpoint: POST /api/projects/{project_id}/config/android/
Create a complete ASO project with multiple markets:
Request (Using New App - Multiple Markets):
{
"app": {
"name": "WhatsApp Messenger",
"package_id": "com.whatsapp"
},
"markets": [
{
"country": "us",
"language": "en",
"keywords": [
"messaging app",
"secure messenger",
"whatsapp"
],
"competitors": [
{
"package_id": "org.telegram.messenger",
"country": "us",
"language": "en"
},
{
"package_id": "org.signal.android",
"country": "us",
"language": "en"
}
]
},
{
"country": "de",
"language": "de",
"keywords": [
"Messaging-App",
"sicherer Messenger"
],
"competitors": [
{
"package_id": "org.telegram.messenger",
"country": "de",
"language": "de"
}
]
},
{
"country": "in",
"language": "en",
"keywords": [
"messaging app",
"chat app"
],
"competitors": []
}
],
"notes": "WhatsApp multi-market tracker"
}
Request (Using Existing App):
{
"app_id": "550e8400-e29b-41d4-a716-446655440000",
"markets": [
{
"country": "us",
"language": "en",
"keywords": [
"messaging app",
"secure messenger"
]
},
{
"country": "de",
"language": "de",
"keywords": [
"Messaging-App"
]
}
],
"notes": "Track WhatsApp across markets"
}
Request Fields:
app(object, optional) - New app to track:{name, package_id}- Use if you're creating a new app in the system
-
Cannot be used with
app_id -
app_id(UUID, optional) - Existing app UUID - Use if the app already exists in the system
-
Cannot be used with
app -
markets(object[], required) - Array of markets to track - Each market is
{country, language, keywords[], competitors[]} - At least ONE market required
- Each market can have different keywords and competitors
Market Object Fields:
- country (string, required) - ISO 2-letter country code
- language (string, required) - ISO language code
- keywords (string[], optional) - Words to track in THIS market only
- Auto-converted to lowercase
- Example: ["messaging app", "secure messenger"]
- competitors (object[], optional) - Competing apps in THIS market
- Array of: {app_id OR package_id, country, language}
- Must match the market's country/language
- Each competitor app must already exist in system
notes(string, optional) - Internal documentation- Your own notes about this project strategy
Rule: Either app or app_id must be provided (not both)
Rule: Each competitor's country/language must match its market's country/language
Common Country/Language Values:
- United States: {"country": "us", "language": "en"}
- Germany: {"country": "de", "language": "de"}
- Japan: {"country": "jp", "language": "ja"}
- India: {"country": "in", "language": "en"}
- Brazil: {"country": "br", "language": "pt"}
- United Kingdom: {"country": "gb", "language": "en"}
- France: {"country": "fr", "language": "fr"}
- Spain: {"country": "es", "language": "es"}
- Italy: {"country": "it", "language": "it"}
Example Package IDs (Android):
- WhatsApp: com.whatsapp
- Telegram: org.telegram.messenger
- Signal: org.signal.android
- Instagram: com.instagram.android
- Facebook: com.facebook.katana
Response (201 Created):
{
"id": "bb0e8400-e29b-41d4-a716-446655440006",
"app": {
"id": "550e8400-e29b-41d4-a716-446655440000",
"name": "WhatsApp Messenger",
"package_id": "com.whatsapp",
"country_languages": [
{
"id": "770e8400-e29b-41d4-a716-446655440002",
"country": "us",
"language": "en",
"keywords": [
{"id": "880e8400-e29b-41d4-a716-446655440003", "text": "messaging app"},
{"id": "990e8400-e29b-41d4-a716-446655440004", "text": "secure messenger"}
]
},
{
"id": "771e8400-e29b-41d4-a716-446655440003",
"country": "de",
"language": "de",
"keywords": [
{"id": "881e8400-e29b-41d4-a716-446655440004", "text": "messaging-app"}
]
}
]
},
"markets": [
{
"id": "770e8400-e29b-41d4-a716-446655440002",
"country": "us",
"language": "en",
"keywords": [
{"id": "880e8400-e29b-41d4-a716-446655440003", "text": "messaging app"},
{"id": "990e8400-e29b-41d4-a716-446655440004", "text": "secure messenger"}
]
},
{
"id": "771e8400-e29b-41d4-a716-446655440003",
"country": "de",
"language": "de",
"keywords": [
{"id": "881e8400-e29b-41d4-a716-446655440004", "text": "messaging-app"}
]
}
],
"keywords": [
{"id": "880e8400-e29b-41d4-a716-446655440003", "text": "messaging app"},
{"id": "990e8400-e29b-41d4-a716-446655440004", "text": "secure messenger"},
{"id": "881e8400-e29b-41d4-a716-446655440004", "text": "messaging-app"}
],
"competitors": [
{
"id": "aa0e8400-e29b-41d4-a716-446655440005",
"app_id": "24c2d6a5-9e8c-4f1a-b2e3-7f8d9a0c1b2e",
"app": {
"id": "24c2d6a5-9e8c-4f1a-b2e3-7f8d9a0c1b2e",
"name": "Telegram Messenger",
"package_id": "org.telegram.messenger"
},
"country": "us",
"language": "en"
},
{
"id": "ab0e8400-e29b-41d4-a716-446655440006",
"app_id": "34d3e7b6-0f9d-5g2b-c3f4-8g9e0b1d2c3f",
"app": {
"id": "34d3e7b6-0f9d-5g2b-c3f4-8g9e0b1d2c3f",
"name": "Signal Private Messenger",
"package_id": "org.signal.android"
},
"country": "us",
"language": "en"
},
{
"id": "ac0e8400-e29b-41d4-a716-446655440007",
"app_id": "24c2d6a5-9e8c-4f1a-b2e3-7f8d9a0c1b2e",
"app": {
"id": "24c2d6a5-9e8c-4f1a-b2e3-7f8d9a0c1b2e",
"name": "Telegram Messenger",
"package_id": "org.telegram.messenger"
},
"country": "de",
"language": "de"
}
],
"notes": "WhatsApp multi-market tracker",
"created_at": "2024-10-28T12:00:00Z",
"updated_at": "2024-10-28T12:00:00Z"
}
For Apple Projects
Endpoint: POST /api/projects/{project_id}/config/apple/
Create a complete ASO project for iOS with multiple markets:
Request (Using New App - Multiple Markets):
{
"app": {
"name": "WhatsApp Messenger",
"bundle_id": "net.whatsapp.WhatsApp"
},
"markets": [
{
"country": "us",
"language": "en",
"keywords": [
"messaging app",
"secure messenger"
],
"competitors": [
{
"bundle_id": "org.telegram.messenger",
"country": "us",
"language": "en"
}
]
},
{
"country": "de",
"language": "de",
"keywords": [
"Messaging-App"
],
"competitors": []
}
],
"notes": "WhatsApp multi-market tracker"
}
Request (Using Existing App):
{
"app_id": "550e8400-e29b-41d4-a716-446655440000",
"markets": [
{
"country": "us",
"language": "en",
"keywords": [
"messaging app",
"secure messenger"
]
},
{
"country": "de",
"language": "de",
"keywords": [
"Messaging-App"
]
}
],
"notes": "Track WhatsApp across markets"
}
Example Bundle IDs (Apple):
- WhatsApp: net.whatsapp.WhatsApp
- Telegram: org.telegram.messenger
- Signal: org.whispersystems.signal
- Instagram: com.burbn.instagram
- Facebook: com.facebook.Facebook
Response (201 Created):
{
"id": "bb0e8400-e29b-41d4-a716-446655440006",
"app": {
"id": "550e8400-e29b-41d4-a716-446655440000",
"name": "WhatsApp Messenger",
"bundle_id": "net.whatsapp.WhatsApp",
"country_languages": [
{
"id": "770e8400-e29b-41d4-a716-446655440002",
"country": "us",
"language": "en",
"keywords": [
{"id": "880e8400-e29b-41d4-a716-446655440003", "text": "messaging app"},
{"id": "990e8400-e29b-41d4-a716-446655440004", "text": "secure messenger"}
]
},
{
"id": "771e8400-e29b-41d4-a716-446655440003",
"country": "de",
"language": "de",
"keywords": [
{"id": "881e8400-e29b-41d4-a716-446655440004", "text": "messaging-app"}
]
}
]
},
"markets": [
{
"id": "770e8400-e29b-41d4-a716-446655440002",
"country": "us",
"language": "en",
"keywords": [
{"id": "880e8400-e29b-41d4-a716-446655440003", "text": "messaging app"},
{"id": "990e8400-e29b-41d4-a716-446655440004", "text": "secure messenger"}
]
},
{
"id": "771e8400-e29b-41d4-a716-446655440003",
"country": "de",
"language": "de",
"keywords": [
{"id": "881e8400-e29b-41d4-a716-446655440004", "text": "messaging-app"}
]
}
],
"keywords": [
{"id": "880e8400-e29b-41d4-a716-446655440003", "text": "messaging app"},
{"id": "990e8400-e29b-41d4-a716-446655440004", "text": "secure messenger"},
{"id": "881e8400-e29b-41d4-a716-446655440004", "text": "messaging-app"}
],
"competitors": [
{
"id": "aa0e8400-e29b-41d4-a716-446655440005",
"app_id": "24c2d6a5-9e8c-4f1a-b2e3-7f8d9a0c1b2e",
"app": {
"id": "24c2d6a5-9e8c-4f1a-b2e3-7f8d9a0c1b2e",
"name": "Telegram Messenger",
"bundle_id": "org.telegram.messenger"
},
"country": "us",
"language": "en"
}
],
"notes": "WhatsApp multi-market tracker",
"created_at": "2024-10-28T12:00:00Z",
"updated_at": "2024-10-28T12:00:00Z"
}
Complete Example: Single-Request Workflow
Scenario: Track WhatsApp on Android (US/EN market)
Step 1: Create Base Project
curl -X POST http://localhost:8000/api/workspaces/550e8400-e29b-41d4-a716-446655440001/projects/ \
-H "Authorization: Bearer $JWT_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"name": "WhatsApp Android - US Market",
"type": "ASO_ANDROID"
}'
# Returns project_id: 550e8400-e29b-41d4-a716-446655440000
Step 2: Create Complete ASO Project (All-in-One)
# Single request creates: app, market, keywords, and ASO config - ALL AT ONCE!
curl -X POST http://localhost:8000/api/projects/550e8400-e29b-41d4-a716-446655440000/config/android/ \
-H "Authorization: Bearer $JWT_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"app": {
"name": "WhatsApp Messenger",
"package_id": "com.whatsapp"
},
"markets": [
{
"country": "us",
"language": "en",
"keywords": [
"messaging app",
"secure messenger",
"whatsapp"
],
"competitors": []
}
],
"notes": "WhatsApp US market tracker"
}'
Result: - โ WhatsApp app created or retrieved (if exists) - โ US/EN market created - โ 3 keywords added for tracking in US/EN market - โ ASO configuration created with M2M relationships - โ All in ONE atomic transaction!
Response includes complete ASO project with all nested data ready for tracking.
Example with Competitors
Option 1: Using app_id (UUID)
curl -X POST http://localhost:8000/api/projects/550e8400-e29b-41d4-a716-446655440000/config/android/ \
-H "Authorization: Bearer $JWT_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"app": {
"name": "WhatsApp Messenger",
"package_id": "com.whatsapp"
},
"markets": [
{
"country": "us",
"language": "en",
"keywords": [
"messaging app",
"secure messenger"
],
"competitors": [
{
"app_id": "35a92937-223f-4348-9cbd-85039bea2d8f",
"country": "us",
"language": "en"
},
{
"app_id": "14e5b527-2c36-4435-b0b7-d7a2b01a4d87",
"country": "us",
"language": "en"
}
]
}
],
"notes": "Monitor Telegram and Signal by UUID"
}'
Option 2: Using package_id (more human-readable)
curl -X POST http://localhost:8000/api/projects/550e8400-e29b-41d4-a716-446655440000/config/android/ \
-H "Authorization: Bearer $JWT_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"app": {
"name": "WhatsApp Messenger",
"package_id": "com.whatsapp"
},
"markets": [
{
"country": "us",
"language": "en",
"keywords": [
"messaging app",
"secure messenger"
],
"competitors": [
{
"package_id": "org.telegram.messenger",
"country": "us",
"language": "en"
},
{
"package_id": "org.signal.android",
"country": "us",
"language": "en"
}
]
}
],
"notes": "Monitor Telegram and Signal by package_id"
}'
Option 3: Mixed (combine UUID and package_id)
"competitors": [
{
"app_id": "35a92937-223f-4348-9cbd-85039bea2d8f",
"country": "us",
"language": "en"
},
{
"package_id": "org.signal.android",
"country": "us",
"language": "en"
}
]
Important Notes on Competitors:
- Provide either app_id (UUID) or package_id (for Android) / bundle_id (for Apple)
- Competitors must be in the SAME market as the market they're being tracked in
- If tracking WhatsApp in us/en, competitors must also be us/en
- This ensures you're comparing apps in the same geography and language
- country and language must match an existing market localization for that app
- Competitor app must already exist in the system (must be created before adding as competitor)
- If competitor app or market doesn't exist, you'll get a clear error asking you to create it first
Data Model Summary
Android ASO Project Structure (Flattened M2M)
Workspace
โโโ Project (type=ASO_ANDROID)
โโโ ASOAndroidProject (your tracking project)
โโโ app โ AndroidApp (com.whatsapp)
โ โโโ country_languages โ [AndroidAppCountryLanguage]
โ โโโ us/en
โ โโโ de/de
โ โโโ jp/ja
โ
โโโ markets (M2M) โ [AndroidAppCountryLanguage]
โ โโโ us/en (WhatsApp USA)
โ โโโ de/de (WhatsApp Germany)
โ โโโ jp/ja (WhatsApp Japan)
โ
โโโ keywords (M2M) โ [AndroidAppKeyword]
โ โโโ messaging app (us/en market)
โ โโโ secure messenger (us/en market)
โ โโโ messaging-app (de/de market)
โ โโโ ใกใใปใผใธใณใฐใขใใช (jp/ja market)
โ
โโโ competitors (M2M) โ [AndroidAppCountryLanguage]
โโโ Telegram us/en
โโโ Signal us/en
โโโ Telegram de/de
โโโ Telegram jp/ja
Key Relationships:
- app = Single Android app being tracked
- markets = List of country-language pairs you're monitoring
- keywords = All keywords across all markets (each keyword belongs to a market via its ACL)
- competitors = All competitor app markets you're comparing against
Apple ASO Project Structure (Flattened M2M)
Workspace
โโโ Project (type=ASO_APPLE)
โโโ ASOAppleProject (your tracking project)
โโโ app โ AppleApp (net.whatsapp.WhatsApp)
โ โโโ country_languages โ [AppleAppCountryLanguage]
โ โโโ us/en
โ โโโ de/de
โ โโโ jp/ja
โ
โโโ markets (M2M) โ [AppleAppCountryLanguage]
โ โโโ us/en (WhatsApp USA)
โ โโโ de/de (WhatsApp Germany)
โ โโโ jp/ja (WhatsApp Japan)
โ
โโโ keywords (M2M) โ [AppleAppKeyword]
โ โโโ messaging app (us/en market)
โ โโโ secure messenger (us/en market)
โ โโโ messaging-app (de/de market)
โ โโโ ใกใใปใผใธใณใฐใขใใช (jp/ja market)
โ
โโโ competitors (M2M) โ [AppleAppCountryLanguage]
โโโ Telegram us/en
โโโ Signal us/en
โโโ Telegram de/de
โโโ Telegram jp/ja
Key Relationships:
- app = Single Apple app being tracked
- markets = List of country-language pairs you're monitoring
- keywords = All keywords across all markets (each keyword belongs to a market via its ACL)
- competitors = All competitor app markets you're comparing against
Required vs Optional Fields
Base Project (Always Required)
- โ
name- Project name - โ
type- ASO_ANDROID or ASO_APPLE - โ
workspace_id- Parent workspace
App (Always Required)
- โ
name- App display name - โ
package_id(Android) /bundle_id(Apple) - Store ID
ACL (Always Required)
- โ
app_id- Parent app - โ
country- ISO 2-letter code - โ
language- ISO language code
Keywords (Optional)
- โ
acl_id- Parent ACL - โ
text- Keyword to track
ASO Configuration (Required to Complete)
- โ
app_idorapp- Which app to track (one required) - โ
markets- Markets to track (required, at least one) - โ
keywords- Keywords for each market (optional, but recommended) - โ
competitors- Competitor ACLs for each market (optional) - โ
notes- Internal notes (optional)
Best Practices
- Create apps once, reuse many times
- Don't create AndroidApp for "WhatsApp" twice
-
One app per unique package_id/bundle_id
-
Plan your markets upfront
- Create all ACLs you need before keywords
-
Example: If tracking US/EN and US/ES, create both ACLs first
-
Keyword strategy
- Start with 3-5 main keywords per market
- Update keywords based on campaign needs
-
Keywords stored in lowercase automatically
-
Competitor tracking
- Add competitor apps' ACLs to monitor their performance
- Each competitor must be in the SAME market (country/language) it's being tracked in
-
Example: To compare vs Telegram in US/EN, add Telegram's us/en market to competitors
-
Documentation
- Use
notesfield to document strategy - Example: "Competitor analysis for Q4 campaign"
Common Errors
Error: "User not a workspace member" - Ensure you have access to the workspace - Request workspace owner to add you
Error: "Duplicate package_id" - App with this package_id already exists - Use existing app instead of creating new one
Error: "Duplicate country/language combination" - ACL (us/en) already exists for this app - Use existing ACL instead
Error: "User not a workspace member" when adding keywords - Ensure you have workspace admin/owner rights - Contact workspace owner for permission
See Also
- Workspaces & Projects Guide - Manage projects and access
- API Reference - Full API documentation
- Authentication - Get JWT tokens