Who this is for. The front-end developer adding "remember my filter" or "back to the results" behaviour to a listing, a search page or a product finder. Afterwards you can choose the right place for each piece of state and avoid the mix-up that only shows when a visitor has two tabs open.
The URL is the filter state
A filter belongs in the address bar first: it is shareable and bookmarkable, it survives a reload, the back button steps through it, the server renders the page from it, and the page cache can store each combination (Facet state belongs in the URL). A script never holds a filter on its own. Browser storage only answers smaller questions around it: where should "Back to the results" lead, and should a visitor who returns to an unfiltered listing see their last filter again?
Per tab, or per visitor
The two kinds of browser storage differ in one way that decides everything here. localStorage is shared by every tab of the site and lasts until it is cleared. sessionStorage belongs to one tab: it survives reloads and navigation within that tab, and ends when the tab closes.
| State | Belongs to | Store it in |
|---|---|---|
| A list's filter, sort, page or selection; the results to go back to | One tab | sessionStorage |
| A theme, a language, a dismissed banner, a preferred code language | The visitor, in every tab | localStorage |
The failure of getting it wrong is concrete. A visitor opens the blog in two tabs, filters the first to "news" and the second to "recipes", then opens a post in the first tab. With the last filter in localStorage both tabs share one value, so whichever filtered last wins: the first tab's "Back to the results" leads to recipes. With sessionStorage each tab keeps its own. An expiry of a day or so, sometimes added to a filter kept in localStorage, is a sign that the wrong store was chosen: the right lifetime for a tab's state is the tab.
This documentation site follows the rule: your choice between Smarty and Twig in the code samples is a preference for every tab, so it is kept in localStorage.
A "back to the results" link that each tab gets right
The listing remembers, per tab, the URL it was last viewed at, query string included; a post points its back link there when the tab has one, and keeps the plain listing as its default otherwise. Both reads are wrapped, because storage can be unavailable in a private window, and the stored value is checked to be a path on this site before it becomes a link: