◆ replaceState/pushState でがんばる

1a.html には 2 つのリンクがあってどちらも遷移先は 2.html です
1 つめのリンクを押したときは 普通に 2.html に移動して戻るボタンで 1a.html に戻ります
2 つめのリンクを押したときは 2.html に移動しますが 戻るボタンを押すと 1b.html に移動させたいです

[1a.html]
<!doctype html>

<h1>page 1a</h1>
<a id="btn1" href="2.html">button 1</a>
<br />
<a id="btn2" href="2.html">button 2</a>

[1b.html]
<!doctype html>

<h1>page 1b</h1>

[2.html]
<!doctype html>

<h1>page 2</h1>

replaceState

一見無理そうにも思えますが SPA アプリケーションでよく使われる historyAPI を使えば簡単にできます

btn2 を押したときに replaceState で今の URL を戻りたい URL に書き換えます

document.getElementById("btn2").addEventListener("click", eve => {
history.replaceState({}, "", "1b.html")
})

location.replace と違って ページ遷移とかはなく単純に URL バーの表示を置き換えるだけです
1a.html から 2.html を開いたわけですが ブラウザの履歴には 1b.html から 2.html を開いたと記録されます
ページ遷移する前に元のページの URL が変わっているので ブラウザの戻るを押したときにブラウザは書き換えられた URL を開こうとします

これで 1b.html に戻ってこれますね

書き換え後すぐに a タグのページ遷移が起きるので変わったことには通常気がつかないと思います

遷移後のページで戻り先を変える

ページを開くときに戻り先を置き換えるのは簡単でしたが 開かれたページでその制御するのはちょっとむずかしいです

historyAPI では 今の state を置き換えたり 追加することは可能ですが これまでの遷移履歴を変更することはできません
なので 今のページが開かれた時点で前のページというのは確定しています

そうなるとできることは ブラウザバックを検出して目的のページに遷移させることです
一つ前のページは履歴に残り続けますが これはどうしようもないので諦めます

また ページ遷移させるときに 戻るを押したのにページ遷移してしまっては 履歴が増える上に 進むボタンで最初にページ遷移したページに移動できなくなります
そうならないようにちょっと工夫します


目的は
「1a.html が 2.html を開いて 2.html の処理で ブラウザバックすると 1b.html を開くようにする」
ということ

最終的に履歴が

1a.html --> 1b.html --> 2.html

となるようにします

[2.html]
<!doctype html>

<h1>page 2</h1>

<script>
history.replaceState({location_replace: "1b.html"}, "")
history.pushState({}, "", "2.html")

window.addEventListener("popstate", eve => {
if(eve.state && eve.state.location_replace){
location.replace(eve.state.location_replace)
}
})
</script>

2.html が開かれたときの履歴は

1a.html --> 2.html

こうなっています
ここで pushState を使って 2.html をもうひとつ履歴に追加します
また replaceState で 1b.html に置き換えるという情報を付与しておきます

ブラウザバックが実行された時のイベントで 1b.html に置き換えるという情報を受け取って location.replace をします

これで 2.html がロード読み込まれたとき

1a.html

2.html (ここに戻ってきたら 1b.html に置き換え)

2.html ◀ いまここ

戻るを押した時

1a.html

1b.html ◀ いまここ

2.html

となります

target="_blank" の場合

ついでに target="_blank" で別タブで開く場合も考えてみます
別タブなのでもう履歴や戻るボタンは関係ないです

開く元で制御する場合

開く元で制御する場合は単純です
自身を location.replace で置き換えるだけです

[1a.html]
document.getElementById("btn2").addEventListener("click", eve => {
location.replace("1b.html")
})

開かれた側で制御する場合

開かれた側で開いた window を取得するには window.opener を使います

[2.html]
window.opener.location.replace("1b.html")

開く側で noopener をつけていると opener が使えないのでつけないようにする必要があります