Next.js: Intercom widget confuses HeadManager

Created on 29 Nov 2019  Â·  8Comments  Â·  Source: vercel/next.js

Bug report

Describe the bug

I have integrated Intercom using more or less the example code from https://github.com/zeit/customer-support-examples/

Everything works as expected but after opening the intercom widget (i.e. lazyLoading the intercom widget library), I receive this error message in the JavaScript console of my browser:

head-manager.js:67 Uncaught (in promise) TypeError: Cannot read property 'tagName' of null
    at HeadManager.updateElements (head-manager.js:67)
    at head-manager.js:35
    at Array.forEach (<anonymous>)
    at HeadManager.doUpdateHead (head-manager.js:34)
    at head-manager.js:19

The reason is the following:

I have manually specified

      <Head>
        <meta name="viewport" content="width=device-width" />
      </Head>

in my pages which results in the following rendered html:

<head>
  <meta charset="utf-8">
  <meta name="viewport" content="width=device-width" class="jsx-4258714920 jsx-1921619020">
  …
  <meta name="next-head-count" content="20">
</head>

When loading the Intercom library and opening an Intercom chat it removes the viewport meta tag to temporarily set its own viewport meta tag, head now looks something like this:

<head>
  <meta charset="utf-8">
  …
  <meta name="next-head-count" content="20">
  …
  <meta id="intercom-viewport-meta" name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=0">
</head>

After closing the Intercom chat the original viewport meta tag gets restored:

<head>
  <meta charset="utf-8">
  …
  <meta name="next-head-count" content="20">
  …
  <meta name="viewport" content="width=device-width" class="jsx-4258714920 jsx-1921619020">
</head>

As you can see, the viewport meta tag that was initially before the next-head-count has now been moved after the next-head-count tag which leads to the error message above as there is now one head tag less than the number stored in next-head-count. So in my case the loop tries to iterate over 20 elements before the next-head-count tag but now only finds 19:

https://github.com/zeit/next.js/blob/11c7ca33d1fb164dd30e1e421b4d1c02fa10ad2d/packages/next/client/head-manager.js#L62-L70

I admit that this might rather be an issue with the Intercom library but I'm still wondering what you would suggest how to deal with such situations?

How should the HeadManager react when other JavaScript components manipulate the <head> tags that should be under HeadManager's control?

To Reproduce

See Bug report above.

Expected behavior

Not sure, to be honest.

System information

  • OS: any
  • Browser (if applies) Chrome
  • Version of Next.js: 9.1.4
bug needs investigation

Most helpful comment

This was fixed in #16758

All 8 comments

I have the same issue. It's only happened on mobile, not on the desktop.

@blueshark226124 indeed, the relevant code is in https://js.intercomcdn.com/frame.4006c444.js and contains a check for display/window size. This is why you see the error only on mobile.

Comments added by myself:

    73: function(e, t, n) {
        "use strict";
        n.d(t, "a", function() {
            return i
        }),
        n.d(t, "c", function() {
            return o
        }),
        n.d(t, "b", function() {
            return a
        }),
        n.d(t, "d", function() {
            return u
        });
        var r = []
          , i = function(e) {
            s(e);
            var t = document.createElement("meta");
            t.id = "intercom-viewport-meta",
            t.name = "viewport",
            t.content = "width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=0",
            e.document.getElementsByTagName("head")[0].appendChild(t)
        }
          , o = function(e) {
            var t = e.document.getElementById("intercom-viewport-meta");
            t && (t.parentNode.removeChild(t),
            c(e))
        }
          , a = function(e) {
            // Only do all of this on small (mobile-size) screens:
            return void 0 === e && (e = window.parent),
            e.innerWidth <= 450 || e.innerWidth <= 900 && e.innerHeight <= 450
        }
          , s = function(e) {
            // Clone all current <meta name=viewport> tags to an array and remove them from the DOM:
            [].slice.call(e.document.getElementsByTagName("meta")).forEach(function(e) {
                "viewport" === e.name && (r.push(e.cloneNode()),
                e.parentNode.removeChild(e))
            })
        }
          , c = function(e) {
            // Here the previously removed meta elements get appended to the end of <head>
            for (var t = r.length, n = 0; n < t; n++)
                e.document.getElementsByTagName("head")[0].appendChild(r.pop())
        }
          , u = function() {
            try {
                a() && !window.parent.navigator.standalone && window.parent.scrollTo(0, 0)
            } catch (e) {}
        }
    },

Great work on the report! I have the same issue, and can only confirm only mobile. I'm not sure the workaround..?

I have the same issue on all devices.

Having the Same issue but with payment gateway script that opens a pop-up that adds some tags and removes when we close the popup

I think this also happens with Plausible's (https://github.com/plausible/analytics/issues/295) tracking script. Though I don't have a 100% proof this is caused by Plausible.

@puneetverma05 I have this same issue with razorpay. next@canary fixes it.

This was fixed in #16758

Was this page helpful?
0 / 5 - 0 ratings

Related issues

formula349 picture formula349  Â·  3Comments

wagerfield picture wagerfield  Â·  3Comments

renatorib picture renatorib  Â·  3Comments

havefive picture havefive  Â·  3Comments

sospedra picture sospedra  Â·  3Comments