Is this static or animated? If it’s static, there are simpler ways. I might try MASH or XGen instancing, or maybe creating a plane under the surface and generating a high-res displacement map that pushes the plane above the surface to create the bubbles. I’m guessing animated, though.
The challenge I’ve always found with particles is that once you want high detail like this you start needing a very high particle resolution, and that makes things slow and a lot harder to control. Surface tension seems to be hard to simulate, which also makes things like water droplets and flowing rivulets difficult. I’m also interested in how people would do this sort of thing (just for education in my case), but I have a feeling most of the answers will be “I gave up years ago and use expensive dedicated water simulation packages instead”…