How do I detect if a user has got to a page using the back button?

83,405

Solution 1

Use a hidden form. Form data is preserved (typically) in browsers when you reload or hit the back button to return to a page. The following goes in your page (probably near the bottom):

<form name="ignore_me">
    <input type="hidden" id="page_is_dirty" name="page_is_dirty" value="0" />
</form>

In your javascript, you will need the following:

var dirty_bit = document.getElementById('page_is_dirty');
if (dirty_bit.value == '1') window.location.reload();
function mark_page_dirty() {
    dirty_bit.value = '1';
}

The js that sniffs the form has to execute after the html is fully parsed, but you could put both the form and the js inline at the top of the page (js second) if user latency is a serious concern.

Solution 2

Here is a very easy modern solution to this old problem.

if (window.performance && window.performance.navigation.type === window.performance.navigation.TYPE_BACK_FORWARD) {
    alert('Got here using the browser "Back" or "Forward" button.');
}

window.performance is currently supported by all major browsers.

Solution 3

This article explains it. See the code below: http://www.webkit.org/blog/516/webkit-page-cache-ii-the-unload-event/

<html>
    <head>
        <script>

            function pageShown(evt){
                if (evt.persisted) {
                    alert("pageshow event handler called.  The page was just restored from the Page Cache (eg. From the Back button.");
                } else {
                    alert("pageshow event handler called for the initial load.  This is the same as the load event.");
                }
            }

            function pageHidden(evt){
                if (evt.persisted) {
                    alert("pagehide event handler called.  The page was suspended and placed into the Page Cache.");
                } else {
                    alert("pagehide event handler called for page destruction.  This is the same as the unload event.");
                }
            }

            window.addEventListener("pageshow", pageShown, false);
            window.addEventListener("pagehide", pageHidden, false);

        </script>
    </head>
    <body>
        <a href="http://www.webkit.org/">Click for WebKit</a>
    </body>
</html>

Solution 4

You can solve it using the onbeforeunload event:

window.onbeforeunload = function () { }

Having an onbeforeunload empty event manager function means the page will be re-built every single time it is accessed. Javascripts will re-run, server-side scripts will be re-run, the page will be built as if the user was hitting it for the very first time, even if the user got to the page just by hitting the back or forward button.

Here is the full code of an example:

<html>
<head>
<title>onbeforeunload.html</title>
<script>
window.onbeforeunload = function () { }

function myfun()
{
   alert("The page has been refreshed.");
}
</script>

<body onload="myfun()">

Hello World!<br>

</body>
</html>

Try it, navigate away this page and then get back using "Back" or "Forward" buttons in your browser.

It works fine in IE, FF and Chrome.

Of course you can do whatever you want inside myfun function.

More info: http://www.hunlock.com/blogs/Mastering_The_Back_Button_With_Javascript

Solution 5

For modern browsers, this seems to be the right way now:

const perfEntries = performance.getEntriesByType('navigation');
if (perfEntries.length && perfEntries[0].type === 'back_forward') {
  console.log('User got here from Back or Forward button.');
}

This is still "Experimental" as of Jan 2020, but seems to be supported well.

https://developer.mozilla.org/en-US/docs/Web/API/PerformanceNavigationTiming

Share:
83,405

Related videos on Youtube

Tom
Author by

Tom

I'm mostly a Python &amp; JavaScript developer at the moment but I've done a lot of things...

Updated on February 06, 2021

Comments

  • Tom
    Tom over 3 years

    This question is similar to Track when user hits back button on the browser, but not the same... I have a solution and am posting it here for reference and feedback. If anyone has any better options, I'm all ears!

    The situation is that I have a page with an "in place edit", a la flickr. I.e. there is a "click here to add a description" DIV, which when clicked turns into a TEXTAREA with Save and Cancel buttons. Clicking Save posts the data to the server to update the database and puts the new description in the DIV in place of the TEXTAREA. If the page is refreshed, the new description is displayed from the database with a "click to edit" option. Fairly standard web 2.0 stuff these days.

    The issue is that if:

    1. the page is loaded without the description
    2. a description is added by the user
    3. the page is navigated away from by clicking a link
    4. the user clicks the back button

    Then what is displayed (from the browser's cache) is the version of the page without the dynamically modified DIV containing the new description.

    This is a fairly big problem as the user assumes that their update has been lost and won't necessarily understand that they need to refresh the page to see the changes.

    So, the question is: How can you flag a page as being modified after it has loaded, and then detect when the user "goes back to it" and force a refresh in that situation?

    • innaM
      innaM about 15 years
      How is this different from the question you quoted?
    • Tom
      Tom about 15 years
      the question is similar, but i think the environment and hence the answer is different, i could be wrong. my interpretation of what an issue may be that would be solved with the other solution is: user clicks a tab on a page that is loaded by ajax, then another tab and so on. clicking the back button would take you back to a different page, not the previous tab. they want to cycle back through the "ajax history" within the "page history". at least that's my impression of what the Yahoo Browser History Manager is supposed to do. i was after something a little more basic.
    • innaM
      innaM about 15 years
      The accepted answer features your iframe trick.
  • Tom
    Tom about 15 years
    Not that I know of, but I haven't tested it fully. getElementById isn't supported in some older browsers, but that's easy to swap out for jquery or something if required.
  • Tom
    Tom about 13 years
    "Form data is preserved (typically) in browsers" -- are you able to expand on that? is it not preserved in some browsers? or in some situations?
  • Nick White
    Nick White about 13 years
    Actually, let me list all the ways I can think of this to go wrong. (1) Opera keeps the full state of the page and won't re-execute the js. (2) If your cache settings are tweaked to force the page to load from the server on back-button, the form data might get lost, which is fine for the purposes of this question. (3) Phone browsers have a much smaller cache and the browser may have already dropped the page from cache (not a problem for these purposes).
  • SajithK
    SajithK over 12 years
    In some browsers hidden tags are not preserved. So you could use hidden text tag instead of using hidden input tag. <input type="text" value="0" id='txt' name='txt' style="display: none" />
  • Joren
    Joren about 12 years
    This worked great for me. I'm sure it has situations when it breaks down, but every solution will for this problem.
  • Slava Abakumov
    Slava Abakumov over 9 years
    This is a good answer, works in latest Chrome 40 / Firefox 35. IE11 doesn't support those events, though.
  • woheras
    woheras about 9 years
    It is not working on iPhone with Safari browser, try it, when you click back button, js is not called again.
  • Chris Schmitz
    Chris Schmitz over 8 years
    Note, this doesn't seem to work without the name attribute being set.
  • Cristian
    Cristian almost 8 years
    According to caniuse.com/#feat=page-transition-events page transition events are actually supported in IE11+ As we speak there's 88% global coverage of the feature
  • Auguste Van Nieuwenhuyzen
    Auguste Van Nieuwenhuyzen over 7 years
    AFAIK this doesn't work if you're using HTTPS. There is a hack with using 'autocomplete' on the form - but this seems like a poor approach to me.
  • Ryan
    Ryan over 6 years
    I had not heard of this. I just found this documentation (developer.mozilla.org/en-US/docs/Web/API/Performance/naviga‌​tion) and would be interested to hear you elaborate (e.g. why the need for window.performance && window.performance.navigation.type instead of just window.performance.navigation.TYPE_BACK_FORWARD?).
  • Bassem
    Bassem over 6 years
    window.performance.navigation.TYPE_BACK_FORWARD is a constant that is always equal to 2. So it is just used for comparison.
  • Albaz
    Albaz about 6 years
    Performance.navigation supported at all devices except andorid & opera mini but no problem its very nice (developer.mozilla.org/en-US/docs/Web/API/Performance/naviga‌​tion)
  • Albaz
    Albaz about 6 years
    its nice workaround but how do you it if he want to detect this every time , when i opened the site and closed it , i need to detect just when i opened and go back before closing
  • instead
    instead about 6 years
    Beware, this script cause infinite loop! At least in Firefox. Because after reload, value of hidden input is still equal to 1. Bassem solution, seems to be the only one actually working.
  • Luke
    Luke over 5 years
    Doesn't appear to work in Chrome as far as I can tell. A console.log only gets triggered in the else statement (added for testing) regardless of how I access the page.
  • Jakob
    Jakob over 5 years
    Works in Safari for me
  • RubberDuckRabbit
    RubberDuckRabbit about 5 years
    Looks like performance.navigation is deprecated and it's suggested to instead use developer.mozilla.org/en-US/docs/Web/API/…
  • Chris Moschini
    Chris Moschini about 5 years
    This will crash your script on Safari - both Mac and mobile
  • Kelderic
    Kelderic almost 5 years
    Firefox v70 will support performance.navigation = 2 for back button hits. Up until v70, it incorrectly returned 1.
  • Kelderic
    Kelderic almost 5 years
    FYI, Chrome returns event.persisted = false, even when hitting from back button. You must use window.performance.navigation or PerformanceNavigationTiming for Chrome.
  • Aboozar Rajabi
    Aboozar Rajabi over 3 years
    better to use === instead of ==
  • Protector one
    Protector one over 3 years
  • M.Arjmandi
    M.Arjmandi over 3 years
    Not working on modern browsers. Hidden inputs not preserved in some browsers
  • Dr. DS
    Dr. DS almost 3 years
  • Nurkartiko
    Nurkartiko over 2 years
    there are other answer here improve this deprecation
  • rugabarbo
    rugabarbo over 2 years
    It's not supported by Safari (desktop and mobile).
  • ban-geoengineering
    ban-geoengineering about 2 years
    Looks good from where I'm sitting (just next to the window).
  • getup8
    getup8 almost 2 years
    @rugabarbo it seems to be supported by Safari now