--- name: ppp-pricing description: Propose purchasing power parity (PPP) prices for a mobile app's or game's in-app products in every App Store territory and Google Play region with `storebound prices ppp` - World Bank ICP PPP factors (bundled, CC BY 4.0), The Economist Big Mac index (downloaded on the owner's machine) or the owner's own factor CSV, clamped to a floor and ceiling of the US price, snapped to real App Store price points and clean local Play prices, written as a price sheet that `storebound prices import` applies after its own diff and confirmation. Use when the user asks for regional pricing, PPP or purchasing power pricing, cheaper prices in emerging markets, localized price tiers, or "price by country". --- # PPP pricing (proposal sheet, both stores) CLI: `storebound` (or `bunx storebound`, or `bun /cli/index.ts`). This command only proposes. It writes a CSV and prints a diff; nothing reaches a store until the owner runs `storebound prices import` and confirms there. ## What it computes Per product, store and region: - `usd = base x PPP factor / exchange rate` (the PPP price, back in US dollars at the market rate). - Clamped to `floor..ceiling` of the base (defaults 0.3 and 1.2): no region below 30 % or above 120 % of the US price. - Converted to the currency the store uses there (some App Store storefronts are priced in USD or EUR) and snapped: - App Store, online: the nearest real price point of that product in that territory (Apple takes nothing else). - Google Play, and the App Store offline: a clean local ending (x.99, 0.x9, whole numbers ending in 9; round numbers for JPY, KRW, VND, IDR, HUF, CLP, TWD and every value over 1000). Snapping can move a price a little past the floor or ceiling. - The US row is always the base itself. ## Data sources (the owner picks one) - `worldbank` (default, bundled `cli/data/ppp-worldbank.json`): World Bank PA.NUS.PPP (PPP conversion factor, GDP) and PA.NUS.FCRF (official exchange rate), latest year per country, CC BY 4.0. Euro regions use the euro area rate. Countries without recent data (Taiwan, Venezuela, a few small territories) get no row. - `bigmac`: The Economist Big Mac index (implied PPP = local Big Mac price / US price). Not bundled (its licence leaves third-party data out). Download it on the owner's machine first: `storebound prices ppp --update-bigmac` (writes `.storebound/ppp-bigmac.json`, gitignored). - `file`: the owner's own CSV, `region,factor,currency,fx` (`fx` optional: then the bundled rate when the currency matches). `--file ` or `prices.ppp.file` in the config. Config (optional): `prices: { ppp: { source, file, floor, ceiling, out } }`. ## Steps 1. `storebound check`. Products must be in `products[]` with a `usd` base. For real App Store price points the products must exist on App Store Connect (`storebound apple iap`); otherwise those rows are offline proposals. 2. Dry run and show it to the owner: `storebound prices ppp --dry` (all products; `--only id1,id2`, `--store apple|play`, `--base 4.99` to try another US price, `--floor 0.4 --ceiling 1.1`, `--source bigmac|file`, `--offline` to skip every store read). It prints the sheet, the diff against the stores' current prices (offline: every row "new") and the regions without a proposal. 3. The owner decides: base price, floor and ceiling, and which regions to keep. Then write the sheet: `storebound prices ppp` (default `store/prices-ppp.csv`, `--out` to change it). 4. The owner reviews and edits the CSV (delete rows to keep a store's own conversion, round to a house price ladder). 5. Apply through the normal price sheet flow: `storebound prices import --csv store/prices-ppp.csv --dry`, then `--yes --allow-price-changes` after the owner says yes to that diff (see store-iap-setup; `--yes` alone never changes an existing price). Import checks Apple price points (the error lists the neighbours) and Play's region currencies. ## Read before applying - PPP is a proposal, not a rule. Cheaper prices can cannibalize, invite VPN arbitrage on web checkouts and change revenue; the owner decides region by region. - Taxes: App Store and Play customer prices are tax-inclusive in most regions (EU VAT, UK VAT, many others), while the US base is tax-exclusive. PPP factors describe consumer price levels including taxes, so the sheet is a customer price; proceeds per region differ by the local tax. Play's convertRegionPrices also returns tax-inclusive prices. - Offline values: Apple only accepts its own price points and its own storefront currency (USD or EUR in many smaller storefronts). An offline sheet is a starting point; `prices import --dry` shows what does not fit. - An App Store price increase cannot be undone once it starts. - Data age: `--json` and the log show the dataset's year and retrieval date. Maintainers refresh the bundled file with `bun tools/update-ppp.ts` (`--check` prints its age). ## Output `--json` prints `{ source: {name, year, retrieved, url, license}, base: {product: usd}, floor, ceiling, online: {apple, play}, rows: [{product, store, region, currency, price, factor, fx, usdEquivalent, clamped, snappedFrom, snap}], skipped: [{product, store, region, why}], diff, out, written }`. Use `--json --dry` for a read-only run. ## Out of scope - Writing prices to a store (that is `storebound prices import`, after the owner's yes). - Subscriptions (their prices go through `storebound apple subscriptions` / `play subscriptions` with a prices CSV). - Choosing the base price or deciding which markets to discount: the owner's call.