On 1 January 2026 Bulgaria replaced the lev with the euro. For about a year before and after that date, millions of people had the same small problem: how much is this in euro? How much was my salary in leva? Is this price right?
In June 2025 I launched eurocalculator.eu, a converter between the lev and the euro, in Bulgarian. It is about as simple as a website gets, and it has had 3.3 million page views from 309,000 users so far. Here is what building a site for a one-time event taught me.
The traffic curve of a one-time event
The chart tells most of the story:
- June 2025: the site goes live, seven months before the changeover.
- July 2025: a first bump after EU finance ministers took the final decision on 8 July and confirmed the conversion rate.
- August to December 2025: a steady 5,000 to 10,000 views a day, with a clear weekly rhythm. Shops had to show prices in both currencies from 8 August, so people checked prices all the time.
- The first days of January 2026: a spike to about 70,000 views a day.
- February 2026 onwards: a long tail. Today it is about 2,000 views a day.
Most of the traffic came in a few weeks around the changeover. If I had launched in December, the site would probably not have ranked in time. Launching early was the most important decision I made.
Two inputs and one constant
The conversion rate is fixed: 1 EUR = 1.95583 BGN. It is not a random number: the lev was pegged one to one to the Deutsche Mark, and 1.95583 is the rate at which the Mark was converted to the euro. So the core of the site is two inputs and a constant:
const exchangeRate = 1.95583; // fixed, never changes bgnInput.addEventListener('input', () => { const bgn = parseFloat(bgnInput.value); eurInput.value = isNaN(bgn) ? '' : (bgn / exchangeRate).toFixed(2); }); Type in either field and the other one updates. There is no server call, no API and no build step. The official rule is just as short: divide the lev amount by the full rate, without rounding the rate, and round the result to two decimals, rounding up when the third decimal is 5 or more.
And yes, that is floating point with money. In this direction it is safe: since 195583 is odd, the exact result can never land on a half cent, so there is no tie for toFixed() to get wrong.
The rest of the page answers the questions people actually asked: why exactly 1.95583, how prices are recalculated, where to exchange leva, and whether prices would double (they didn't: in the countries that joined before Bulgaria the one-time effect was a few tenths of a percent).
For the "how much did this go up?" part, a currency converter is not enough: you convert the old price to euro and then need the percentage change between the two prices. That is what my other small tool, Percentage Calculator, does with its increase and decrease mode, and the euro calculator links to it in the footer.
A feature built to be deleted
In January 2026 both currencies were in circulation for one month. You could pay in leva, but the change came back in euro, unless the shop had no euro coins yet. That makes for some confusing moments at the till.
So on 20 December 2025 I added a change calculator: enter the bill and the amount paid, each in leva or euro, and it shows the change in euro and its value in leva. The logic converts everything to euro first:
const billInEur = convert(bill, billCurrency, 'EUR'); const paidInEur = convert(paid, paidCurrency, 'EUR'); const change = paidInEur - billInEur; if (change < 0) { changeInfo.textContent = `Not enough: ${format2(Math.abs(change))} € missing.`; } else { changeEur.value = format2(change); } On 1 February 2026 the lev stopped being legal tender, and on 31 January I removed the change calculator. It lived for six weeks, and that was exactly right. Not every feature has to last forever, and it is easier to remove one when you knew from the start that you would.
Talking to users through the page
A converter doesn't need a blog, but people had questions about the site itself. "Will the calculator still work in 2026?" came up again and again in the last days of December.
So the home page has a short news section: the launch, the change calculator, the first million visits, its removal, and the answer to that question. Yes, it stays: people will need to convert old invoices, tax returns, salaries and pensions for years. Each news item is also a BlogPosting in the page's schema.org data, and the questions and answers are a FAQPage, so search engines can read them.
Life after the changeover
After January the main question disappeared, but the visitors kept asking for other currencies. In March 2026 I added seven new pairs: the euro against the US dollar, Turkish lira, British pound, Romanian leu, Czech koruna, Hungarian forint and Polish złoty.
Unlike the lev, these rates change every day. The European Central Bank publishes its euro reference rates at around 16:00 CET on working days, and its Data Portal has a simple API that can return the latest value as CSV:
$url = 'https://data-api.ecb.europa.eu/service/data/EXR/D.USD.EUR.SP00.A' . '?lastNObservations=1&format=csvdata'; $ch = curl_init($url); curl_setopt_array($ch, [CURLOPT_RETURNTRANSFER => true, CURLOPT_TIMEOUT => 15]); $csv = curl_exec($ch); if ($csv === false || curl_getinfo($ch, CURLINFO_HTTP_CODE) !== 200) { return null; // keep the last saved rate } // Line 0 is the header, line 1 holds the data: // EXR.D.USD.EUR.SP00.A,D,USD,EUR,SP00,A,2026-11-06,1.1165,... $lines = preg_split('/\R/', trim($csv)); $fields = str_getcsv($lines[1] ?? '', ',', '"', ''); if (count($fields) < 8 || !is_numeric($fields[7])) { return null; } $date = $fields[6]; // TIME_PERIOD $rate = (float) $fields[7]; // OBS_VALUE The rate is saved in a small JSON file, so most visits just read the cache. After the publication time, a visit triggers a new request to the ECB. If the ECB can't be reached, the page keeps the last saved rate. If even that is missing, it uses an approximate rate. The page always says which one you are looking at: today's ECB reference rate, the last saved one, or an approximate rate.
Small touches
- "Save the app" button. The site is installable as a PWA. The button uses
beforeinstallpromptwhere the browser supports it, and otherwise shows short instructions: "Share, then Add to Home Screen" on iPhone, Ctrl+D elsewhere. For a tool people open again and again during a few months, being one tap away matters. - A row of flags at the top switches between the currency pairs. In a site with no menu, it is the navigation.
What I learned
- For an event with a date, launch months before it. The traffic comes in a few weeks, and by then it is too late to start ranking.
- Plan for the day after. The first question goes away, but the visitors, the links and the trust stay. Ask them what they need next.
- Keep the URL alive. Some people will need to convert an old lev amount for years.
- Simple is enough. Two inputs, a constant and a few lines of JavaScript answered a question that 309,000 people had.
And the money?
The site runs Google AdSense with Auto ads, so Google decides where the ads go and I don't place them by hand. I won't share the exact amount, but so far it has earned a five-figure sum in US dollars. Not bad for two inputs and a constant.
Have you built something for a one-time event? What did you do with it after the event was over? I'd love to hear in the comments.
I wrote this post with the help of, based on the site's code and my own data. I checked the facts and numbers before publishing.



