Have you ever looked at your app's revenue and wondered why certain markets aren't converting — even with good reviews and solid ratings? One underappreciated culprit is incorrect price tier configuration.
Both the App Store and Google Play use a pricing tier system. The assumption that your $0.99 US price automatically translates into the right local price in Japan, India, or Brazil is often wrong — and leaving those settings on autopilot can mean you're either pricing yourself out of a market or leaving money on the table.
Understanding the App Store Price Point System
Since Apple revamped its pricing system in 2023, developers can set country-specific prices independently rather than relying solely on automatic currency conversion from a base price.
The key distinction: automatic conversion applies the current exchange rate, which ignores purchasing power parity (PPP). A price that feels affordable in the US can feel expensive in India, and a price that feels cheap in Japan can actually undercut your perceived quality.
For example:
- US: $0.99
- Japan: ¥160 (auto-converted) vs ¥250 (recommended override)
- India: ₹99 (auto-converted) vs ₹79 (adjusted for PPP)
Japan is an interesting case — ¥160 is sometimes too cheap. Japanese consumers associate very low prices with low quality. ¥250 or ¥480 often converts better because it lands in the "feels right for the value" zone.
Google Play's Local Pricing Feature
Google Play Console makes country-specific pricing straightforward. Under Monetization → Products → In-app products, you can navigate to the "Price conversion" tab and click "Get local prices."
This feature surfaces Google's recommended local prices based on purchasing power data for each country. Apps that adopt these recommendations consistently report improved install-to-purchase conversion rates in emerging markets.
Markets where local pricing tends to have the biggest impact:
- Brazil (BRL)
- India (INR)
- Mexico (MXN)
- Turkey (TRY)
- Southeast Asia (various)
In these markets, the gap between exchange-rate-based prices and PPP-appropriate prices is largest — which means the optimization opportunity is greatest.
Analyzing Country-Level Revenue with Antigravity
Here's a practical script that pulls App Store Connect sales data and identifies pricing optimization opportunities:
# analyze_revenue_by_country.py
import requests
import jwt
import time
from datetime import datetime, timedelta
def get_auth_token(key_id: str, issuer_id: str, private_key: str) -> str:
"""Generate a JWT token for App Store Connect API authentication."""
payload = {
"iss": issuer_id,
"iat": int(time.time()),
"exp": int(time.time()) + 1200,
"aud": "appstoreconnect-v1",
}
return jwt.encode(
payload,
private_key,
algorithm="ES256",
headers={"alg": "ES256", "kid": key_id},
)
def get_sales_by_country(
app_id: str,
key_id: str,
issuer_id: str,
private_key: str,
days: int = 30,
) -> dict:
"""Fetch country-level revenue for the past N days."""
token = get_auth_token(key_id, issuer_id, private_key)
headers = {"Authorization": f"Bearer {token}"}
country_revenue = {}
for i in range(days):
date = (datetime.now() - timedelta(days=i)).strftime("%Y-%m-%d")
resp = requests.get(
"https://api.appstoreconnect.apple.com/v1/salesReports",
headers=headers,
params={
"filter[reportType]": "SALES",
"filter[reportSubType]": "SUMMARY",
"filter[frequency]": "DAILY",
"filter[reportDate]": date,
"filter[vendorNumber]": "YOUR_VENDOR_NUMBER",
},
)
if resp.status_code == 200:
for row in parse_tsv_report(resp.content):
country = row.get("Country Code", "UNKNOWN")
revenue = float(row.get("Developer Proceeds", 0))
country_revenue[country] = country_revenue.get(country, 0) + revenue
return dict(sorted(country_revenue.items(), key=lambda x: x[1], reverse=True))
def parse_tsv_report(content: bytes) -> list:
"""Parse Apple's gzip-compressed TSV sales report."""
import csv
import io
import gzip
try:
content = gzip.decompress(content)
except Exception:
pass
reader = csv.DictReader(io.StringIO(content.decode("utf-8")), delimiter="\t")
return list(reader)
def analyze_pricing_opportunity(country_revenue: dict) -> list:
"""Identify countries where pricing optimization is most likely to help."""
# Reference PPP indices (approximate, 2026)
PPP_INDEX = {
"JP": 0.72, # Japan — yen weakness makes auto-conversion prices feel off
"IN": 0.32, # India — local pricing is critical here
"BR": 0.45, # Brazil
"MX": 0.41, # Mexico
"TR": 0.28, # Turkey
"US": 1.00, # Baseline
"GB": 0.91,
"DE": 0.85,
"AU": 0.86,
"KR": 0.70,
}
opportunities = []
for country, revenue in country_revenue.items():
if country in PPP_INDEX:
ppp = PPP_INDEX[country]
priority = "HIGH" if ppp < 0.50 else "MEDIUM" if ppp < 0.75 else None
if priority:
opportunities.append({
"country": country,
"current_revenue": revenue,
"ppp_index": ppp,
"action": "Consider local pricing to improve conversion",
"priority": priority,
})
return sorted(opportunities, key=lambda x: x["current_revenue"], reverse=True)
# Run analysis
if __name__ == "__main__":
revenue = get_sales_by_country(
app_id="YOUR_APP_ID",
key_id="YOUR_KEY_ID",
issuer_id="YOUR_ISSUER_ID",
private_key=open("AuthKey.p8").read(),
days=30,
)
print("=== Top 10 Countries by Revenue ===")
for i, (country, amount) in enumerate(list(revenue.items())[:10], 1):
print(f"{i:2}. {country}: ${amount:.2f}")
opportunities = analyze_pricing_opportunity(revenue)
print("\n=== Pricing Optimization Opportunities ===")
for opp in opportunities:
print(f"[{opp['priority']}] {opp['country']}: {opp['action']}")Common Mistakes in Subscription Pricing
Three patterns come up repeatedly when independent developers misconfigure pricing:
Unified global pricing. Setting $4.99/month in the US and letting every other country auto-convert. In India, that becomes ₹415/month — which at local purchasing power feels like a premium-tier charge for a utility app. Conversion drops significantly.
Too-cheap Japanese pricing. ¥250/month sounds affordable, but it can signal low quality to Japanese users. The ¥480–¥600 range tends to feel "appropriately priced" for a well-made app. Counterintuitively, raising the price sometimes improves both conversion and retention.
Fear of price changes. Many developers avoid changing prices because they worry about upsetting existing subscribers. Apple's "Preserve Price" feature lets you lock in existing subscribers at their current price while charging new subscribers the updated amount. Price iteration is more flexible than most developers realize.
Where to Start: A Practical Checklist
Pricing optimization is a cycle: analyze → hypothesize → test → measure. Start here:
-
Check your current country breakdown. App Store Connect → Sales and Trends → Territory. Understand what percentage of revenue each market contributes.
-
Find high-volume, low-revenue markets. Countries with strong download numbers but weak revenue often indicate a pricing mismatch. The app is resonating — the price isn't.
-
Test one country at a time. Don't change all markets simultaneously. Pick one high-opportunity country (India is a common starting point), adjust pricing, and measure for 90 days.
-
Compare cohort conversion rates, not just total revenue. Use RevenueCat or App Store Connect's cohort reports to compare install-to-purchase rates before and after the change. Total revenue can be noisy; conversion rate is the cleaner signal.
Pricing isn't a set-and-forget decision. Building a regular review cycle — quarterly or around major feature releases — is what separates developers who systematically grow revenue from those who leave it to chance.
For deeper monetization automation, the premium article Subscription Churn Prevention Pipeline with RevenueCat and Antigravity AI covers building a churn prediction model and automated win-back flows from scratch.