Purchasing power, not exchange rates
A price that feels fair in Chicago feels very different in Chennai, and converting dollars to rupees at the bank rate does not fix that. What does is purchasing-power parity: how much local money buys what one US dollar buys at home. EasyPPP uses the World Bank’s household-consumption purchasing-power figures. They compare the cost of the things people actually buy, rather than machinery or government spending, which makes them the right basket for a subscription or a digital product. For each country, that figure divided by the current exchange rate gives a price level: India sits around 0.2, Germany around 0.8, Switzerland above 1. Exchange rates move every day and the World Bank figures move once a year, so EasyPPP stores the two separately and refreshes rates nightly. The tiers themselves are built from the yearly data so your prices do not drift from one day to the next.Five buckets per currency
Rather than one price per country, countries are grouped into tiers by their price level relative to your base price’s home market. For a USD base price the home market is the United States; for EUR it is Germany.
The base bucket is every country within about 15% of the home market. Below it, countries are banded so that the members of each tier are priced alike, and each tier pays the median of its members rounded to the nearest 5%. A few markets are more expensive than the home market, so they pay more than the base price. Other base currencies get their own tiers from the same method, 138 currencies in all.
There is one true purchasing-power level per country, so the tiers are the same for every EasyPPP merchant. There is nothing to configure and nothing to keep up to date.
From a page view to a Price
- Your page calls
/v1/pricewith your base Price IDs. - EasyPPP works out the visitor’s country from their request. No location more precise than the country is used or returned.
- The country’s tier for your base currency selects the sibling Price. A visitor in the base bucket, a visitor whose country cannot be determined, or a visitor arriving through a VPN or proxy (when the VPN guard is on) gets your base Price. The response says only that the price was not localized.
- The response returns the Stripe Price ID to charge, plus an estimate of its amount in the visitor’s currency at last night’s exchange rate, formatted for display.
A worked example
Your Pro plan is$100. Importing it creates four siblings in USD: $70, $45, $35 and $130.
A visitor from India loads the page. India is in the Deep tier for USD, so the response points Checkout at the $35 sibling and shows the visitor roughly ₹3,350, using that night’s rate. Stripe charges 35 USD. A visitor from Canada is in the base bucket and sees about CA$136, with Checkout pointed at your original $100 Price.
What the estimate is, and is not
display and amount are there so the visitor sees a familiar number. They are converted from the Price’s own currency at a rate refreshed each night, and rates_as_of tells you which one. Stripe charges the Price in its own currency, which is always your base currency. The Price ID is the authority; the estimate is a courtesy.