Intercom ECMASCRIPT6 Tag Manager Error

chdonncha picture chdonncha · Feb 13, 2018 · Viewed 10k times · Source

I previously successfully setup intercom using Google Tag Manager. Haven't touched it for a couple of months and go to make a new tag but I'm presented with this error coming from the intercom tag:

Error at line 6, character 243: this language feature is only supported for ECMASCRIPT6 mode or better: block-scoped function declaration. Use --language_in=ECMASCRIPT6 or ECMASCRIPT6_STRICT or higher to enable ES6 features.

My script for intercom hasn't changed since it originally worked:

<script>
  window.intercomSettings = {
    app_id: "key"
  };
</script>
<script>(function(){var w=window;var ic=w.Intercom;if(typeof ic==="function"){ic('reattach_activator');ic('update',intercomSettings);}else{var d=document;var i=function(){i.c(arguments)};i.q=[];i.c=function(args){i.q.push(args)};w.Intercom=i;function l(){var s=d.createElement('script');s.type='text/javascript';s.async=true;s.src='https://widget.intercom.io/widget/key';var x=d.getElementsByTagName('script')[0];x.parentNode.insertBefore(s,x);}if(w.attachEvent){w.attachEvent('onload',l);}else{w.addEventListener('load',l,false);}}})()</script>

If anyone has encountered this error and has any advise or tips on how to solve it, it would be much appreciated.

Answer

Eike Pierstorff picture Eike Pierstorff · Feb 13, 2018

Before GTM wraps the code into a minimized JavaScript file to inject it into a page the code goes through a linter; the issue here is that Google sometimes changes the rules for the linter to make them more strict (this has popped up a few times on the GTM forum). Since this is not announced anywhere it occasionally breaks tags that have been working previously.

The problem here seems to be that you tag declare a function inside an if/else block. You can see this when you "beautify" your file:

<script>
    window.intercomSettings = {
        app_id: "key"
    };
</script>
<script>
    (function() {
        var w = window;
        var ic = w.Intercom;
        if (typeof ic === "function") {
            ic('reattach_activator');
            ic('update', intercomSettings);
        } else {
            var d = document;
            var i = function() {
                i.c(arguments)
            };
            i.q = [];
            i.c = function(args) {
                i.q.push(args)
            };
            w.Intercom = i;

            function l() {
                var s = d.createElement('script');
                s.type = 'text/javascript';
                s.async = true;
                s.src = 'https://widget.intercom.io/widget/key';
                var x = d.getElementsByTagName('script')[0];
                x.parentNode.insertBefore(s, x);
            }
            if (w.attachEvent) {
                w.attachEvent('onload', l);
            } else {
                w.addEventListener('load', l, false);
            }
        }
    })()
</script>

The "l" function is declared inside the "else" block and Google's linter does not like that (since previous versions of Javascript technically do not have a block scope for functions, this has only been introduced with ES6).

While I am certain that there is a correct way to fix this an easy way out would be to move the declaration of "l" outside the block:

<script>
    (function() {
        var w = window;

        function l() {
            var s = d.createElement('script');
            s.type = 'text/javascript';
            s.async = true;
            s.src = 'https://widget.intercom.io/widget/key';
            var x = d.getElementsByTagName('script')[0];
            x.parentNode.insertBefore(s, x);
        }
        var ic = w.Intercom;
        if (typeof ic === "function") {
            ic('reattach_activator');
            ic('update', intercomSettings);
        } else {
            var d = document;
            var i = function() {
                i.c(arguments)
            };
            i.q = [];
            i.c = function(args) {
                i.q.push(args)
            };
            w.Intercom = i;


            if (w.attachEvent) {
                w.attachEvent('onload', l);
            } else {
                w.addEventListener('load', l, false);
            }
        }
    })()
</script>

Does not look like it should have side effects and the tag works now (at least when I try it).