Popup when leaving website

written by paul on January 29th, 2008 @ 07:45 PM

On my current project, we had a requirement to pop up a message to the user when they leave our site (e.g., close the browser window). We discovered a number of sites talking about a window.close event, but it is not supported in modern browsers (IE 6, Firefox 2, Safari 2). The closest event is an unload event which gets fired when the page is unloaded.

We tried using this event in a javascript file that is included on every page:


window.onunload = popup;

function popup() {
  alert('I see you are leaving the site');
}

Unfortunately, an unload event is fired when the user leaves the page for any reason (such as clicking on a link). We did not want to show the popup if the user clicked on a link which stayed on the site.

Our next idea was to add an onclick to every link which would turn off the popup. Then, if the user clicks a link, nothing happens. If they leave the site another way, they get the popup.

Toby Tripp had the great idea to add these onclicks dynamically in javascript. We use prototype, so the code looks like:


staying_in_site = false;

$$('a').each(function(link) {
  link.observe('click', function() {staying_in_site = true;});
});

window.onunload = popup;

function popup() {
  if(staying_in_site) {
    return;
  }
  alert('I see you are leaving the site');
}

This code creates a variable which determines whether or not to show the popup. Then, we find every link with $$(‘a’). This is a CSS selector which selects all of the a elements. We iterate over these links and add a listener which sets the staying_in_site flag to true. Now, our popup code checks this flag and knows whether the user is staying on the site.

It is important to include this javascript at the bottom of the file (and not in the head). The javascript must be executed after the page is written or the links will not exist yet.

This solution is not perfect, but it accomplishes most of what we need.

Update (1/31/08): Simon Stewart suggested a cleaner method in the comments:


staying_in_site = false;

Event.observe(document.body, 'click', function(event) {
  if (Event.element(event).tagName == 'A') {
    staying_in_site = true;
  }
});

window.onunload = popup;

function popup() {
  if(staying_in_site) {
    return;
  }
  alert('I see you are leaving the site');
}

Instead of attaching an event listener to every link, we can attach a click listener to the whole body. Now, any click will call our function, which checks to see if you clicked on a link. Since we are not iterating over existing links, this javascript does not have to be below the links in the page.

Comments

  • Andy on 30 Jan 03:46

    How does your solutions handle forms? Do you have to register them in the same way?
  • Simon Stewart on 30 Jan 09:32

    Why not just attach a click listener to the body tag and check the original target to see if it's a link? That'll run faster, and means that you're not relying on the location of the script in the page.
  • Rob Wilkerson on 30 Jan 09:59

    With Prototype, it's easy to write the link behavior within the head using Event.oberve ( window, 'unload', ... ). As Simon mentions (sorry, I couldn't write "As Simon says" :-), then you're not reliant on script position.
  • Paul Gross on 30 Jan 13:59

    Simon, that's a great idea. We just switched our implementation to what you suggested. Andy, Simon's solution catches submit buttons as well.
  • conan on 01 Feb 03:20

    if you're responding to clicks on the document body, wouldn't you need to add staying_in_site = false; inside the conditional in case the user clicks on some random bit of background on the page, so that afterwards, when the user really leaves the page (not via a link) the popup function will behave as desired?
  • Paul Gross on 01 Feb 09:45

    Conan, you are correct. I fixed the code sample.
  • Nick on 06 Feb 14:32

    Sorry ... have not much experience in js but I don't understand how the code handles the submit.
  • Paul Gross on 06 Feb 23:35

    Nick, The click listener will catch all clicks, including submit buttons (input tags). So you can modify the line "Event.element(event).tagName == 'A'" to something that checks if the element is an input button.
  • JC Tenney on 28 Mar 07:38

    When I moved the above code in to my site, I got the following error: element has no properties (prototype.js line 2244). Any thoughts as to what it could be?
  • Paul Gross on 28 Mar 10:28

    JC, can you give me more information? What line in your code (not prototype) is causing the error?
  • JC Tenney on 29 Mar 10:42

    That is the problem, I don't know what line of code is causing the problem. I don't know what the problem is. When I look at the stack it says the error is coming from this line: ERROR HERE->Event.observe(document.body, 'click', function(event) { if (Event.element(event).tagName == 'A') { staying_in_site = true; } }); I stepped into the prototype function and it said that element is null.
  • Paul Gross on 30 Mar 11:21

    JC, do you have the code in the body or in the head? If it is in the head, document.body is null. You should either move the code to the body or wrap it with a dom:loaded event: http://www.prototypejs.org/api/document/observe.
  • Gavriel on 15 Apr 12:03

    Nice solution! I found an annoying bug though: when I refresh the page it pops up the alert. Does anyone have a solution to this?
  • Sig on 14 May 20:24

    Hello, I have a couple of questions about your solution (my js skills are poor so I apology if the questions look like silly) 1- what exactly the script should do? does it open a popup when the user closes the browser tab? If so 2- what have I to do in order to make it working? I copied the script at the end of my body page but nothing happens. Thanks and have a good 1!
  • Arnar Sigurdsson on 20 Jan 11:23

    This seems to work fine. However, is there a way to make it not alert when the user hits the back or forward button? If the idea is to do a popup when the user leaves the site, not when he stays within the site, then showing her a popup when going back and forward is not desired.
  • Phill on 21 May 05:35

    I have the same problem, whenever a user refreshes the page or clicks the back botton I get the alert. Was anyone seccussful in fixing this?
  • Tal Fighel on 12 Sep 09:22

    Paul, I am trying to find a code so that when someone leaves my site, they get a pop up that asks them for their email and name. This can get me more and more subscribers. I have tried this before but now I can not find the code. Tal
  • blog marketing on 24 Oct 09:39

    I know this post is rather old but I am looking to do this EXACT same thing with a more recent release of prototype but no matter how I try it I get an error about "element not defined" Could you update this code? You seem to be of the only sites online to provide such code and it is very useful for all sorts of applications.
  • vip on 18 Jan 08:40

    i try to using exitpopup , but i found same trouble in my page , have u complete js script ?
  • Siva Jagadeesan on 09 Feb 17:42

    Cool Paul and Toby. This is a nice trick. It saved me a lot of time.
  • Troy Payne on 28 Apr 14:25

    Guys, This isn't a solution. If a user refreshes the page or hits a back button, they will get the popup. This will be complete if it solves that problem, which I believe is impossible.

Post a comment

Options:

Size

Colors