5

I want to create a function that triggers a GA4 measurement only when the visitor agrees. I created it as follows:

document.querySelector('.cookie').addEventListener('click', function(){

        var ga = document.createElement('script')
        ga.type = 'text/javascript'
        ga.async = true
        ga.src = ('https:' == document.location.protocol ? 'https://ssl' : 'http://www') + '.googletagmanager.com/gtag/js?id=UA-XXXXXX-X'
        var s = document.getElementsByTagName('script')[0]; s.parentNode.insertBefore(ga, s);


        let gat = window.dataLayer = window.dataLayer || [];
        function gtag(){dataLayer.push(arguments);}
                gtag('js', new Date());
                gtag('config', 'UA-XXXXXX-X');
                setCookie('cookie','1',365);
        return false;
    })

The problem is that typescript reports errors: Property 'dataLayer' does not exist on type 'Window & typeof globalThis a gtag - Expected 0 arguments, but got 2.

I've tried various tutorials, installed @types/gtag.js, but the errors persist. Can you advise me what I'm doing wrong? Thank you

Radim
  • 95
  • 5

1 Answers1

2

These Typescript definitions should work:

        interface Window {
        dataLayer:any;
        }
       
        let dataLayer = window.dataLayer || [];
        function gtag(a:string, b:string|object){dataLayer.push(arguments);}
                gtag('js', new Date());
                gtag('config', 'UA-XXXXXX-X');

The first type definition extends the existing window interface with a property "dataLayer". (Windows here with a capital W). Put simply, you need to explain Typescript that the window object has a property dataLayer.

In case the code snippet sits inside a module, probably this definition will help to use it across other modules:

declare global {
  interface Window {
    dataLayer:any;
  }
}

The second problem here is that the function gtag() looks like it has zero arguments, but in reality, the arguments are captured with the variable arguments. Typescript seems to be blind to this approach; hence, we need to define the argument types.

In case you need to send different numbers of arguments to GA, you also could use this broad type definition that excepts any number of arguments (even zero arguments):

function gtag(...args: any[]):void {window.dataLayer.push(arguments);}