Consultancy · Adevinta

Fotocasa: +27% contact and phone leads, with other work

Four of Adevinta's fifteen marketplaces, and one problem they all shared: the back button.

4marketplaces in four countries
~500changes proposed, most still live
+27%contact and phone leads at Fotocasa, with other work
ClientAdevinta: Marktplaats (NL), Subito (IT), Fotocasa (ES), Kijiji (CA)
PlatformFour stacks; Fotocasa in React
ServiceConsultancy, 2022 to 2024
The client

Marktplaats, Subito, Fotocasa and Kijiji

Each marketplace had its own team and its own stack. Marktplaats had code built up over many years. Subito had newer tech, and performance didn't have a fixed place in its process yet.

Visitors hop between search results and listings all day, so they use the back button constantly.

Kijiji, Marktplaats, Fotocasa and Subito
What we found, what we did

The back button on all four, then each marketplace's own challenges

Three things turned up on every site: ads, third-party scripts and the listing images. Underneath, each marketplace had its own list. Their developers built the fixes; I found the problems, put them in order and checked every fix.

What was wrong
What we did

All four marketplaces

bfcache
Every back click loaded the results page from scratch: the ads loaded again and the page jumped. The back/forward cache was blocked by the server headers, a few cookies and the settings of the ad integration.
With those changed, all four got the back/forward cache. In RUM more back clicks came straight from the cache, and in CrUX LCP and INP on the results pages improved.
Process
Performance had no clear owner. People left and documentation got lost.
I trained the teams, so a fix one marketplace built didn't have to be invented again by the next.

Marktplaats

LCP
Five preloads for stylesheets the site no longer used. A preload is a high-priority download, so all five went ahead of the listing images. Too many images loaded eagerly, problems in the data fetching, and more components than the page needed.
Their developers took the five unused preloads out and made only the first listing photos eager, with high fetch priority. They also optimised the CSS and started the data requests earlier or in parallel.

Fotocasa, on web.dev

INP
The open or closed state of the filters dialog lived in the search page, so one click re-rendered all of it.
The state moved into the button. The same click went from 440 to 64 ms in a lab test in DevTools at 4x CPU slowdown.
INPCLS
The number of applied filters sat in state and was set each time the search parameters changed: an extra render, and on some server-rendered pages a layout shift.
The count is worked out from the filters directly. Both went away.
INP
Tracking for a click ran before the screen could update.
It waits for idle time now, so the screen updates first, and it still runs if the visitor closes the tab right after.

Kijiji

TTFB
Slow backend calls, redirects before the page, a heavy server render, and no cache at the edge, so every visitor waited for all of it.
Their developers added a cache at the edge. The backend calls, the redirects and the server render went on their list.
Marktplaats listing photos

On a results page the LCP element is one of the top listing photos, so the order they load in matters. In July 2024 the top photo got the browser’s default priority and only one photo was eager. Their developers changed that: by February 2025 the top three are eager, the first with fetchpriority="high", and the other 47 are marked low so they don’t take bandwidth from it.

Beforemarktplaats.nl/l/auto-s/, July 2024: the first listing photo, no priority
<img data-src="…/985f0a72-ed57-475a-86ff-5c1767a0fc74" src="…/985f0a72-ed57-475a-86ff-5c1767a0fc74" loading="eager"/><img data-src="…/edfc0e83-7d46-4e82-95f9-7aaf08ce182b" src="…/edfc0e83-7d46-4e82-95f9-7aaf08ce182b" loading="lazy" decoding="async"/>
Afterthe same page, February 2025: the first photo high, the rest low, the first three eager
<img data-src="…/93a90a93-fabe-4d44-bb5b-e4e308fe041c" src="…/93a90a93-fabe-4d44-bb5b-e4e308fe041c" loading="eager" fetchPriority="high"/><img data-src="…/7ff3dac9-f0b3-4c04-94fe-5b51310bf160" src="…/7ff3dac9-f0b3-4c04-94fe-5b51310bf160" loading="eager" fetchPriority="low"/><img data-src="…/cddd3037-172a-48bf-a4c9-56d67f449144" src="…/cddd3037-172a-48bf-a4c9-56d67f449144" loading="eager" fetchPriority="low"/><img data-src="…/8defa377-d353-41e5-9d16-808a240f9aaf" src="…/8defa377-d353-41e5-9d16-808a240f9aaf" loading="lazy" decoding="async" fetchPriority="low"/>
A Marktplaats results page in the Internet Archive, July 2024 and February 2025.
The back button

The back button is my favourite fix on these sites, because every visitor uses it. CrUX started counting navigation types in March 2024. That month 16% of the back and forward navigations on Subito, on phones, came from the bfcache. By July it was 68%. Marktplaats followed at the end of the year: from almost nothing to 56% in December 2024, and more since. Each of those is a back click where the browser shows the page from memory instead of loading it again.

50%100%16%Mar 202468%JulOctJan 2025Apr65%Subito, back and forward from the bfcache
50%100%0%Mar 2024JulOct56%Jan 2025Apr57%Marktplaats, back and forward from the bfcache
Share of back and forward navigations on phones that the browser served from the back/forward cache, per month, March 2024 to June 2025. CrUX data in BigQuery.
Fotocasa’s filters

The four developers who wrote the web.dev case study were on my call every two weeks. Their case study has the lab numbers for opening the filters dialog, and the counter code:

Beforestate in the search page
440 ms
INP at 4x CPU slowdown
832 ms
INP at 6x CPU slowdown
Afterstate in the filter button
64 ms
INP at 4x CPU slowdown
232 ms
INP at 6x CPU slowdown
Opening the filters dialog on Fotocasa, measured in Chrome DevTools with CPU throttling. From their case study on web.dev.
Beforethe count kept in state and set in an effect: one more render
const [filtersCount, setFiltersCount] = useState(DEFAULT_COUNTER)useEffect(() => {  const counter = filters    ? Object.keys(filters)        ?.reduce(reducerCounter, [])        ?.filter((param) => searchParams?.[param]).length    : DEFAULT_COUNTER  setFiltersCount(counter)}, [searchParams]);
Afterthe count worked out from the filters
const counter = filters  ? Object.keys(filters)      ?.reduce(reducerCounter, [])      ?.filter((param) => searchParams?.[param]).length  : DEFAULT_COUNTER;
The applied-filters counter on Fotocasa, before and after. Code from the web.dev case study by Andrés Alvarez, Oriol Hilari, Nacho Rodriguez and Joan León (Apache 2.0).
Fotocasa in the field

When INP replaced FID in 2024, nearly all Fotocasa pages dropped from Good to Needs improvement, and some to Poor. The fixes are in their case study on web.dev. In the field data in Search Console, all desktop pages went to Good, and almost all mobile ones. Together with other work, contact and phone lead ads went up 27%.

In CrUX

It started at Fotocasa in November 2022. Marktplaats heard about it and followed in March 2023, Kijiji came in through Marktplaats in 2024, and I worked with their teams until July 2024. Their developers kept going after that, and on three of the four sites you can follow it in CrUX. Fotocasa’s INP on mobile came down from 600 ms in October 2023 to 200 ms by December 2024. Kijiji went from 3.7 seconds LCP in the spring of 2024 to 1.9 by December, and its INP from 375 to 200 ms. Marktplaats was already green and still took its LCP from 2.5 to 1.4 seconds. In February 2024 I was on Marktplaats myself, selling my old childhood Lego, and noticed how much faster it had become. That July I mailed Kijiji’s product lead from a holiday in Sweden: they were 50 ms away from passing on desktop.

200 ms500 ms600 msOct 2023Jan 2024AprJulOct200 msFotocasa, INP on mobile, p75
2.5 s4.0 s2.5 sOct 2023Jan 2024AprJulOct1.4 sMarktplaats, LCP on mobile, p75
2.5 s4.0 s3.6 sOct 2023Jan 20243.7 sAprJulOct1.9 sKijiji, LCP on mobile, p75
200 ms375 msOct 2023Jan 2024AprJulOct200 msKijiji, INP on mobile, p75
Three of the marketplaces in CrUX, phone, October 2023 to December 2024. One bar per month, p75, from Google’s CrUX data in BigQuery. Green is good, orange needs improvement, red is poor.
When Adevinta called, I called my wife: "Guess who's going to speed up Marktplaats?" Her answer: "Finally!"
What we learned

More than 15 CSS files on a slow phone

One of the four asked a phone for more than 15 CSS files. That shows how much it matters: on a mid-range phone on a mobile connection, the stylesheets in the head all have to arrive before anything paints.

A fix only travels when someone owns it

A fix one marketplace built only reached the next when someone owned performance.

Old code that feels risky to remove

On a big site much of the slowness is old: those five preloads at Marktplaats were still in the head because it wasn't clear what would break without them.

Arjen Karel

Several sites, several teams, and nobody owns performance?

One to three days a week, sprint by sprint, working with your developers.

Adevinta: INP at Fotocasa, +27% Leads With Other Work Core Web Vitals Adevinta: INP at Fotocasa, +27% Leads With Other Work