MatteoGabriele / vue-gtag

Global Site Tag plugin for Vue (gtag.js)
https://matteo-gabriele.gitbook.io/vue-gtag/
MIT License
875 stars 67 forks source link

Warning: New Google Analytics 4 properties break the expected behavior of this plugin and cause double page views. #406

Open miketromba opened 2 years ago

miketromba commented 2 years ago

Description

First of all, thank you for all your hard work on this plugin Matteo! I really appreciate it.

When creating new Google Analytics properties, they now default to Google Analytics version 4 (GA4). The problem is: the default behavior of GA4 properties is incompatible with this plugin right now, and causes unwanted and unexpected behavior.

I spent a lot of time this morning pulling my hair out trying to understand why random page view events were being sent even without auto-tracking enabled... I learned that it is caused by the default behavior of new GA4 properties.

By default, when gtag.js is installed, GA4 properties automatically send page view events on page loads and even page changes based on browser history events, as shown with this data stream setting:

image

This totally clashes with the behavior of this plugin, causing there to be lots of double page views, and is very confusing to those who miss this! (I assume many developers will fall into this trap)

Suggestion

I do not have a specific suggestion right now on how to make this library GA4-compatable, but I highly recommend temporarily updating the documentation in the meantime to include a big warning that the plugin is not ready for GA4 and will cause duplicate page views.

I think this will save developers a lot of time!

antonreshetov commented 2 years ago

Any news?

TravisRick commented 2 years ago

Bump.. Any update on this bug?

bruno-71 commented 2 years ago

Is v1 of vue-gtag compatible with GA4? I'm still using Vue2 and would like to use this with the new Google Analytics 4.

pandalion commented 2 years ago

Is this still an issue? Is vue-gtag compatible with Google Analytics 4?

MatteoGabriele commented 2 years ago

Thanks, @miketromba, for your feedback, and sorry for responding to you so late. I will try to look into this, but if any of you know a solution already, don't hesitate to drop it here, and maybe we can fix it and fix it sooner.

MatteoGabriele commented 2 years ago

I am assuming you are using vue-gtag v2

MatteoGabriele commented 2 years ago

I have based my implementation on google's documentation https://developers.google.com/analytics/devguides/collection/gtagjs/pages there's no specification of being GA4 compatible or not

MatteoGabriele commented 2 years ago

I might have found the cause on this line. https://github.com/MatteoGabriele/vue-gtag/blob/master/src/api/pageview.js#L38-L40 I have published a beta version of the fix. Can someone have a look to see if this fixes it? vue-gtag@2.0.2-beta.0 thanks a lot

jasperf commented 2 years ago

@MatteoGabriele would love to test but would need the patch for the legacy version using Vue 2.

miketromba commented 2 years ago

Here's a small plugin that provides basic tracking functions of gtag.js with GA4 properties- without needing any 3rd party libraries. The heavy lifting is done by GA4's default auto-tracking behavior.

It works well on my end, but I suggest you test to make sure it works well in your own project.

Note: if you're not using nuxt, the plugin logic is the same, just adjust the code to work in your vue environment.

Nuxt 3 GA4 plugin plugins/gtag.client.js

Note: make sure to include .client.js at the end which tells Nuxt to only run it on the browser.

const gtagId = "YOUR_GA4_ID"

export default defineNuxtPlugin(() => {

    // Create gtag function & define gtag deps (window.dataLayer array)
    window.dataLayer = window.dataLayer || []
    function gtag(){dataLayer.push(arguments)}
    gtag('js', new Date())

    // Config with gtagId & send initial page view
    gtag('config', gtagId, { send_page_view: true })

    // Inject gtag function
    return { provide: { gtag } }
})

Nuxt 2 GA4 plugin plugins/gtag.client.js

Note: make sure to include .client.js at the end which tells Nuxt to only run it on the browser.

const gtagId = "YOUR_GA4_ID"

export default (_, inject) => {

    // Create gtag function & define gtag deps (window.dataLayer array)
    window.dataLayer = window.dataLayer || []
    function gtag(){dataLayer.push(arguments)}
    gtag('js', new Date())

    // Config with gtagId & send initial page view
    gtag('config', gtagId, { send_page_view: true })

    // Inject gtag function
    inject('gtag', gtag)
}

Then make sure to add this script to your nuxt config file... (replace YOUR_GA4_ID in the URL)

nuxt.config.ts (Nuxt 3)

export default defineNuxtConfig({
  //...
  app: {
    head: {
      script: [
        { src: 'https://www.googletagmanager.com/gtag/js?id=YOUR_GA4_ID', async: true }
      ]
    }
  }
})

nuxt.config.js (Nuxt 2)

export default {
  //...
  head: {
    script: [
      { src: 'https://www.googletagmanager.com/gtag/js?id=YOUR_GA4_ID', async: true }
    ]
  }
}

By default, this should auto-track router navigation in your app, but if you want to tap into the other gtag features, use the injected $gtag property.

jasperf commented 2 years ago

Am using the Vue 2 version and it does seem to work with GA4 as well so not having a lot of issues. Thanks for sharing @miketromba . Perhaps @MatteoGabriele can put it to use.

stefan-golus commented 2 years ago

miketromba for nuxt 3 code dosesn't work at all and has a lot of console warnings related with window object.

miketromba commented 2 years ago

@nomtek-sgolus That might be because it's trying to run on the server side (if you're using SSR) - I have my file named gtag.client.js - this tells Nuxt 3 to only run it on the browser.

image

stefan-golus commented 2 years ago

@nomtek-sgolus That might be because it's trying to run on the server side (if you're using SSR) - I have my file named gtag.client.js - this tells Nuxt 3 to only run it on the browser.

image

Got it, and yep - it works now 👍

notflip commented 1 year ago

Here's a small plugin that provides basic tracking functions of gtag.js with GA4 properties- without needing any 3rd party libraries. The heavy lifting is done by GA4's default auto-tracking behavior.

It works well on my end, but I suggest you test to make sure it works well in your own project.

Note: if you're not using nuxt, the plugin logic is the same, just adjust the code to work in your vue environment.

Nuxt 3 GA4 plugin plugins/gtag.client.js

Note: make sure to include .client.js at the end which tells Nuxt to only run it on the browser.

const gtagId = "YOUR_GA4_ID"

export default defineNuxtPlugin(() => {

    // Create gtag function & define gtag deps (window.dataLayer array)
    window.dataLayer = window.dataLayer || []
    function gtag(){dataLayer.push(arguments)}
    gtag('js', new Date())

    // Config with gtagId & send initial page view
    gtag('config', gtagId, { send_page_view: true })

    // Inject gtag function
    return { provide: { gtag } }
})

Nuxt 2 GA4 plugin plugins/gtag.client.js

Note: make sure to include .client.js at the end which tells Nuxt to only run it on the browser.

const gtagId = "YOUR_GA4_ID"

export default (_, inject) => {

    // Create gtag function & define gtag deps (window.dataLayer array)
    window.dataLayer = window.dataLayer || []
    function gtag(){dataLayer.push(arguments)}
    gtag('js', new Date())

    // Config with gtagId & send initial page view
    gtag('config', gtagId, { send_page_view: true })

    // Inject gtag function
    inject('gtag', gtag)
}

Then make sure to add this script to your nuxt config file... (replace YOUR_GA4_ID in the URL)

nuxt.config.ts (Nuxt 3)

export default defineNuxtConfig({
  //...
  app: {
    head: {
      script: [
        { src: 'https://www.googletagmanager.com/gtag/js?id=YOUR_GA4_ID', async: true }
      ]
    }
  }
})

nuxt.config.js (Nuxt 2)

export default {
  //...
  head: {
    script: [
      { src: 'https://www.googletagmanager.com/gtag/js?id=YOUR_GA4_ID', async: true }
    ]
  }
}

By default, this should auto-track router navigation in your app, but if you want to tap into the other gtag features, use the injected $gtag property.

Does this allow the use of this.$gtag.event to trigger events on certain button clicks? Thanks

miketromba commented 1 year ago

@notflip The $gtag property is just a normal gtag.js object, so you can see all of the possibilities in Google's official docs:

Gtag.js - https://developers.google.com/tag-platform/gtagjs Gtag event tracking - https://developers.google.com/tag-platform/devguides/events

ap-arto commented 1 year ago

I might have found the cause on this line. https://github.com/MatteoGabriele/vue-gtag/blob/master/src/api/pageview.js#L38-L40 I have published a beta version of the fix. Can someone have a look to see if this fixes it? vue-gtag@2.0.2-beta.0 thanks a lot

Yes, it's fixed the double pageview issue. Can you add it to the v1 as well, please?

notflip commented 1 year ago

I might have found the cause on this line. https://github.com/MatteoGabriele/vue-gtag/blob/master/src/api/pageview.js#L38-L40 I have published a beta version of the fix. Can someone have a look to see if this fixes it? vue-gtag@2.0.2-beta.0 thanks a lot

Yes, it's fixed the double pageview issue. Can you add it to the v1 as well, please?

What code are you using to implement vue-gtag? Thanks! Will test with you