I want to integrade hubspot chat interface in my Rails 4 + Turbolinks application. I have configured Google Tag Manager to show support chat interface in each page load event which is working fine.
GTM tag (custom html)
<!-- Start of HubSpot Embed Code -->
<script type="text/javascript" id="hs-script-loader" async defer src="//js.hs-scripts.com/xxxxxx.js"></script>
<!-- End of HubSpot Embed Code -->
PROBLEM
For debugging I have followed
how-do-i-know-if-my-hubspot-tracking-code-is-working
I can see this tag added to document body (DOM) by inspecting element or by checking it into browser's view page source. Also Network tab show the network call done to js.hs-script.com
.
EXPECTED
I had this issue as well and solved it by removing any existing Hubspot scripts from the header before (re-)including the Hubspot script loader. I just added the following script in my view directly before adding the Hubspot loader:
<script>
// Remove Hubspot <head> scripts after a Turbolinks page load
// so it can re-initialize properly. Paste this code immediately
// before the hubspot loading script in the <body>
(function() {
var scripts, script;
// Remove scripts added by hs-scriptloader
scripts = document.querySelectorAll('script[data-loader="hs-scriptloader"]');
for (var script of scripts) {
script.remove();
}
// Remove Hubspot Analytics
script = document.getElementById('hs-analytics');
if (script != undefined) {
script.remove();
}
// Avoid duplicate chat warning and allow chat to load
window.hubspot_live_messages_running = undefined
})()
</script>
<!-- Now add the script to load Hubspot-->
<script async="" defer="defer" id="hs-script-loader" src="//js.hs-scripts.com/xxxxxxx.js" type="text/javascript"></script>
It's still a brittle solution since Hubspot could change the selectors (data-loader etc.) at any time.
The hubspot code inserts 2 js files into the <head>
and injects some inline stylesheets into the <body>
- one of the js files (conversations-embed.js) creates a div with the id #hubspot-messages-iframe-container
. As its name suggests, it contains an iframe with the chat window. It also adds a bunch of css to the body.
The main problem here is that Turbolinks replaces everything in the <body>
per page change, leaving the hubspot script unaware of the fact that a page has been changed. Since everything is replaced, the div injected by the script and the css disappears.
My first try was to clone the chat container div into a window variable, and use appendChild(clonedNode)
to the event.data.newBody
element within the turbolinks:before-render
event. While this kinda works, it isn't very elegant. It disappears and reappears each time you change a page. Also, the state was not carried over so if I closed the window it would be open at the next page and so on.
What does work is to move the #hubspot-messages-iframe-container
out of the body into the html tag itself, leaving it out of harms way from turbolinks. It's state is kept (open, closed, etc...) and does not blink or have any side effects. Remember that you have to manually remove it from the pages you may not want it on.
I know it's a bit hacky, but it works and until they have some sort of api to reinitialse the chat window this is a workaround:
document.addEventListener("turbolinks:load", function() {
let targetNode = document.body
let config = { childList: true }
let callback = function() {
if (document.body.querySelector('#hubspot-messages-iframe-container')) {
document.documentElement.appendChild(
document.getElementById('hubspot-messages-iframe-container')
)
observer.disconnect()
}
}
let observer = new MutationObserver(callback)
if (!document.querySelector("html > #hubspot-messages-iframe-container")) {
observer.observe(targetNode, config)
}
})
You will also need to copy the style injected into the body, since Turbolinks will also replace this. This is what I ended up with (converted to Sass):
html.hs-messages-widget-open.hs-messages-mobile
height: 100% !important
overflow: hidden !important
position: relative !important
body
height: 100% !important
overflow: hidden !important
position: relative !important
margin: 0 !important
#hubspot-messages-iframe-container
display: initial !important
z-index: 2147483647
position: fixed !important
bottom: 0 !important
right: 0 !important
&.internal
z-index: 1016
iframe
min-width: 108px
.shadow
display: initial !important
z-index: -1
position: absolute
width: 0
height: 0
bottom: 0
right: 0
content: ""
&.internal
display: none !important
&.active
width: 400px
height: 400px
background: radial-gradient(ellipse at bottom right, rgba(29, 39, 54, 0.16) 0, rgba(29, 39, 54, 0) 72%)
iframe
display: initial !important
width: 100% !important
height: 100% !important
border: none !important
position: absolute !important
bottom: 0 !important
right: 0 !important
background: transparent !important
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With