Answering my own question, I chose to go for the simpler solution suggested by @MaxArt in his comment.
- Generate a random ID for a page
- Since I use angularjs, I do this $on('$routeChangeSuccess') or $on('$routeUpdate')
- without angularjs, I suppose I would do this onpopstate
- Store a mapping from this random ID to all the URL information that I need (in my case, search and path) in sessionStorage
- Include a search parameter from=the ID of the current page in outgoing links that go forward in the conceptual hierarchy of my app
- When the custom back button is clicked, look up the state I come from in sessionStorage using the from seach parameter
- if found, go back to that URL
- if not found (user navigated to this page directlry), go back to the default URL for the previous view in the app's hierarchy
Rationale for taking this approach over the more general approach of building a history of past URLs:
- As mentioned, the pushState API does NOT provide access to past URLs
- Integrating History.js, which does provide that information, into angularjs does not seem trivial
- angularjs uses the history API internally: it would need to be changed to instead use History
- Implementing custom code to record the URL history in sessionStorage is also not trivial. The main problem is that, lacking integration with the browser's history, there does not seem to be a general way to know if a visited page is new or it was reached by going back one or more steps in the browser history. I'd be happy to be corrected on this if someone can suggest a solution (1)
- Using History.js or any equivalent solution that wraps all history.pushState with additional code, requires pretty much all links on the page to be wrapped in History.pushState, otherwise URL changes do not show up in the History.
(1) How do I retrieve if the popstate event comes from back or forward actions with the HTML5 pushstate?