2

I run an e-commerce website and we have various third-party JavaScript that add click handlers to links and forms and then insert a delay to make sure the tracking goes through. The delay is inserted by burning CPU and running a for or while loop until a certain date is passed either 350 ms later (Marketo / Munchkin) or 500ms for Visual Website Optimizer. Combined this is almost 1 second!

Sometimes, maybe the delay is nice so tracking can be more reliable. However, we don't want this to happen when you click most links on our site because it adds up to 1 second of delay for the user. With that big a delay, there goes all the other performance optimizations we've done!

Unfortunately, we need a lot of the functionality of these scripts (like Visual Website Optimizer and Marketo) so we can't remove them.

Is it possible to remove the handlers they've added or prevent them from firing, given that I don't have references to them?

jon_wu
  • 1,113
  • 11
  • 26
  • To remove events you can use [unbind](http://api.jquery.com/unbind/). – SnakeDrak Nov 21 '15 at 12:02
  • Did you find out why/ in what places you get doubled waiting time in some cases ? As you said it should not be longer than 500 ms max. – shershen Nov 21 '15 at 21:07
  • I dug deeper to find out that there's 500 ms (VWO) + 350 ms (Marketo). Basically, any click on a link (a tag) gets tracked. For Visual Website Optimizer, this happens naively even if they don't up tracking anything, but may go away if no A/B tests are active (but then what's the point in having it anyways). For Marketo, it seems like all the time. VWO also starts the infinite spin with form submissions. I noticed this when I saw my loading spinner was lagging on our AJAX login and solved a little of the jank from the CPU spin by at least deferring the analytics call, but still - it's very sad. – jon_wu Nov 22 '15 at 05:45

4 Answers4

2

You can use unbind to remove events.

If you need know the event name or type, you can see with Chrome Dev Tools

Another method is capture the event and stop the propagation.

EDIT: If the event if not launched with jQuery, you can use removeEventListener or set null the property event.

Community
  • 1
  • 1
SnakeDrak
  • 3,406
  • 4
  • 28
  • 41
  • 1
    unbind will only remove jQuery events. – yosiweinreb Nov 21 '15 at 12:34
  • Originally, my premise was that you couldn't get a reference to handlers. I've now found that I have 2 cases which can be handled differently. VWO uses jQuery onmousedown so I *can* use unbind to remove its tracking. Since it's not namespaced though, you may end up removing other handlers by accident. I'm not sure if there's an easy way to find the right one, but maybe by using internal jQuery methods to get the reference you could guess. When there is tracking, you can't kill the delay, but I've asked them to add a variable or I'm considering proxying their script to rewrite it. – jon_wu Nov 23 '15 at 12:52
  • With Marketo, I don't think it's possible to remove their onbeforeunload since it was added with addEventListener and we have no reference to the handler. However, I found a workaround for this case where I can set the delay to 0 ms so I don't need to disable the tracking. That fits my use case, but the answer to my question in general seems to be that you can't remove things you don't have a reference to. – jon_wu Nov 23 '15 at 12:53
0

You cannot remove the event listener without the reference to the handler function, but what you can do do is to clone the element.

var elements = document.getElementsByTagName('a');
for(var i =0 ; i < elements.length; i++){
    var cloned = elements[i].cloneNode(true);
    elements[i].parentNode.replaceChild(cloned, elements[i])
}
yosiweinreb
  • 475
  • 4
  • 12
  • This doesn't seem feasible because VWO and Marketo track all form submissions and link clicks everywhere on the page. Since new elements inserted dynamically get tracked to, maybe they're using event delegation. My guess was that I was out of luck without the reference to the handler function as you mentioned. Given that I can't clone everything and things might be delegated anyways, am I just stuck? – jon_wu Nov 21 '15 at 19:28
-1

Well an alternative workaround might be to change the setTimeout functionality to work without or with smaller delay

window.oldSetTimeout = window.setTimeout;
window.setTimeout = function(func, delay) {
   //change the delay value here
   return window.oldSetTimeout(function() {
       func();
   }, delay);
};
yosiweinreb
  • 475
  • 4
  • 12
  • Overwriting default methods (or prototypes) is generally a bad practice. That will lead to numerous hard to spot behaviors across all the page – shershen Nov 21 '15 at 21:06
  • Agree, but as i said this is a workaround. as a results of using 3rd party scripts – yosiweinreb Nov 21 '15 at 21:07
  • Using workaround one would generally expect to solve the problem in some dirty / sophisticated way, but this will just break more that fix as to me – shershen Nov 21 '15 at 21:09
  • The way these scripts and many tracking ones add a delay is ugly. They basically sping the CPU. For example, I traced the minified Visual Website Optimizer code and they call this with a value of 500 to pause for 500 ms: `function V(a) { for (var b = a, a = a + (new Date).getTime(); (new Date).getTime() < a; ) ; h(Ha, b) }` Since it's in a not a global and was defined by a third party in a closure, I don't think I can change this. `setTimeout` isn't used. – jon_wu Nov 22 '15 at 05:33
-1

You can use pure javascript to remove the event listeners,

At the start of your program just call a function to remove the event listener, something like this

var domElement = document.getElementById('elementWithEventListener');
domElement.removeEventListener('click',listener)

And yes, you will have to find out what listeners are getting fired.

Check out Event listeners for more info.

Gaurav_soni
  • 6,064
  • 8
  • 32
  • 49
  • 1
    This seems like what I'd do if I could, but I mentioned I don't have a reference to the listener since I don't control the scripts adding the listener. That's my main challenge here. – jon_wu Nov 22 '15 at 05:29
  • Do you know on which elements the listeners are attached to ? – Gaurav_soni Nov 24 '15 at 06:17
  • Yes. All links in Marketo and listening on body for mousedown with VWO to catch everything bubbling up. For my specific issues, I've actually gotten VWO to add a new configuration option which is awesome and I found one in Marketo's Munchkin snippet. As for the general issue, it seems like there's no way to `removeEventListener` without a reference to the listener itself. https://developer.appcelerator.com/question/127638/why-does-removeeventlistener-need-a-callback and http://stackoverflow.com/questions/26845535/removeeventlistener-without-knowing-the-function. – jon_wu Nov 24 '15 at 14:39