Turbo and other external JS libraries colliding for HTTP 406 errors

I have a relatively obscure but highly difficult bug to fix. I have two external JS libraries (Heap and Inspectlet), both used for analytics purposes, that are colliding with Turbo and causing errors in our Rails app.

When hard refreshing a page and then submitting a form — which is supposed to be submitted by Turbo as a TURBO_STREAM — it is submitted as HTML and, as a result, responded with a 406 (as we don’t have a render for html format).

This appears to happen because these other JS libraries are also hijacking the form submit event in an effort to send analytics. And once they hijack that event, Turbo no longer hijacks it and submits the form correctly as a TURBO_STREAM.

I’ve confirmed that removing these two libraries does indeed fix the 406 error. I’ve also been able to make it work by ensuring uBlock (or another ad blocker) is active, which doesn’t load the analytics JS libraries. Interestingly, I’ve been unable to reproduce this in a development environment on localhost.

Does anyone have thoughts on how this could be fixed? Thanks!

@iseff Did you ever find a solution to this problem? We’re currently running into what appears to be the same issue. The problem has only occurred when including heap on the page, however it does not always happen. It seems to come and go based on load order. It generally happens more if the page is hard reloaded, but it does not always happen.

For anyone else who runs into this in the future. We ended up solving our specific problem with Heap and Turbo by making sure the Heap script executed after Turbo was executed. In our case we were loading our application JS with type=“module” which is deferred but the heap script was not.

@eliot we have had the same issue. Did you consider wrapping the Heap script in a turbo:load event listener?

Yes @chrisjgilbert that probably would have worked. In our case we didn’t want the Heap script to fire on every Turbo visit. I’m not super familiar with Heap or how it should be initialized, but other members on our team had problems with the Heap script loading on every turbo:load. Our other fix was to wrap the Heap script in a DOMContentLoaded event, which fires only once after any deferred scripts are executed.

@eliot interesting. We’ve opted to wrap Heap in the turbo:load event and thus far have had no issues but we have only been testing it for a short period. Do you know what issues your team members ran into with that? Wrapping it in DOMContentLoaded sounds like a good option.

Looks like we were getting some console errors heap.push is not a function. This heap doc has more info Heap.push is not a function Console Error - Heap Help Center but this was caused by loading multiple instances of the heap script on the same page.

Ok great - thanks that’s very useful to know. I’ll keep my eye out for those…!

@eliot out of interest did you have any issues with the analytics being logged ok?

We have Turbo disabled on links and often force reload the page and everything appears to be working ok. However, when I enable Turbo on links, it looks like when navigating that link click events are logged after the page view event is logged…

I also wondered if there was a possibility we’d see page view events getting logged twice but that hasn’t been the case.

I’m curious if you were able to nail this down. I’ve just discovered an issue where roughly one in every 3 loads, Heap prevents turbo frames from correctly working.

@evdevdev we have the Heap snippet last in the <head> and wrapped in the following:

<script type="text/javascript" defer>
  document.addEventListener("turbo:load", function() {
   ... heap snippet in here
  });
</script>

It’s doesn’t interfere with Turbo this way and we’ve only had a small number of Heap related JS errors but not enough to revisit this.

1 Like

@chrisjgilbert Thank you so much for providing that! I’ll give it a try and see if it fixes the issue.

FWIW, I was browsing the Heap changelog and I came across this:

[HEAP-38084] Prevent href interception for turbo frame elements
[HEAP-38638] Add data-heap-turbo attribute to prevent href interception for turbo frame elements

It seems like Heap was aware of this issue in January, 2023. However, I am continuing to get the problem (with easy reproduction) today.

Sadly, from what I can find, there is zero documentation of data-heap-turbo. (And support refuses to provide any answers.)

@evdevdev that’s a really interesting find. Our setup seems relatively stable at the moment but we don’t have tons of traffic. If we see more issues in the future i’ll certainly have a look into that so thanks for flagging.

1 Like