This is precisely the way to do this. I have found that every widget added to the Viewport gets its own ZOrder. So, the simplest way to manage this is to have a Root widget that is the only one that is added to the Viewport and to add other widgets to this Root. You could have as many root widgets as you would like, but each one would have its own ZOrder.
However, the WidgetComponent handles this with SharedLayerName (as Hellow_Wd mentioned.) So things are already pretty easy if you are dealing with Actors.
For UI’s, though, a more complex and C++'-ey way would be to implement your own Layer management system via the IGameLayerManager. See WidgetComponent to understand how one might do this. This interface is not exposed to Blueprint.