Closed drewbaker closed 5 years ago
I'm pretty sure you can do this with setting it through the this.$gtag('config', 'YOUR_ID'). Give it a try it should work.
Thanks @dohomi, good idea. I wasn't sure if this would allow me to actually start gtag with no ID set in nuxt.config.js
, but good idea.
I tried it like you said, but it crashes with an error that this.$gtag
is not a function when I use it in NuxtServerInit
, because this
is the wrong scope I think. But it feels like we are close. I tired context.app.$gtag
and it also didn't work. Any ideas?
If anyone is curious, this is how I'm doing it.
export const actions = {
async nuxtServerInit(store, context) {
// Get site settings from WordPress and save them to store
let client = context.app.apolloProvider.defaultClient
await client
.query({
query: WpSettingsQuery
})
.then(({ data }) => {
let settings = _get(data, 'generalSettings', {})
let meta = {
title: settings.title,
host: context.req.headers.host,
description: settings.description,
themeScreenshotUrl: settings.themeScreenshotUrl,
gaTrackingCodes: [
settings.gaTrackingCode1,
settings.gaTrackingCode2
]
}
store.commit('SET_SITE_META', meta)
})
// Set GA tracking codes
store.state.siteMeta.gaTrackingCodes.forEach(code => {
// code = UA-XXXX-XX
if (code) {
context.app.$gtag('config', code, {
anonymize_ip: true,
send_page_view: false
})
}
})
}
}
I don't think you necessarily need to put that code into onServerInit. We are talking about GA and that is a client side thingy. Just add this code into a router hook or into your initial layout file on mounted. That should be sufficient in my opinion
By the way: you have to add anyhow an initial ID of GA that the plugin starts to initialise its code. After that you add your custom code. Maybe its just better if you don't rely on this plugin at all and wire up the code in your project individually. If you check out the code base, its very few lines of code you need to place in your app to make it work.
Yeah at this point I think you're right, I'm going to try and convert it into a plugin.
@dohomi I was hoping you might be able to point me in the right direction here, I'm super close.
I have a plugin file loading on client side only.
I largely tried to convert this module into a plugin. But the issue is head.script.push
doesn't result in the script being added on first page load, so this doesn't track the first page load, but it does for all subsequent page transitions.
The issue is that gtag script needs the UA code in it's URL, so I can't just add that into the regular script object in nuxt.config.js
.
// plugins/google.gtag.client.js with "mode": "client
export default ({ store, app: { head, router, context } }, inject) => {
// Remove any empty tracking codes
const codes = store.state.siteMeta.gaTrackingCodes.filter(Boolean)
// // Abort if no codes
if (!codes.length) {
if (context.isDev) console.log('No Google Anlaytics tracking codes set')
return
}
// Abort if in Dev mode, but inject dummy functions so $gtag events don't throw errors
if (context.isDev) {
inject('gtag', () => {})
return
}
// Add script tag to head
head.script.push({
src: `https://www.googletagmanager.com/gtag/js?id=${codes[0]}`,
async: true
})
console.log('added script')
// Include Google gtag code and inject it (so this.$gtag works in pages/components)
window.dataLayer = window.dataLayer || []
function gtag() {
dataLayer.push(arguments)
}
inject('gtag', gtag)
gtag('js', new Date())
// Add tracking codes from Vuex store
codes.forEach(code => {
gtag('config', code, {
send_page_view: false // necessary to avoid duplicated page track on first page load
})
console.log('installed code', code)
// After each router transition, log page event to Google for each code
router.afterEach(to => {
gtag('config', code, { page_path: to.fullPath })
console.log('afterEach', code)
})
})
}
I guess you are looking for something like this:
let script = document.createElement(`script`)
script.defer = true
script.onload = () => {
// set a global var that your ga tag is loaded ?
}
script.src = `https://www.googletagmanager.com/gtag/js?id=${codes[0]}`
document.head.appendChild(script)
wrap this code into a function and just load it as long the script never been loaded before. I hope this leads you to the right way
For future reference, this is what I ended up with and it seems to work great. The only thing I' not sure on is @dohomi has defer = true
on the script, but google has async = true
so I went with that instead.
export default ({ store, app: { router, context } }, inject) => {
// Remove any empty tracking codes
const codes = store.state.siteMeta.gaTrackingCodes.filter(Boolean)
// Abort if no codes
if (!codes.length) {
if (context.isDev) console.log('No Google Anlaytics tracking codes set')
return
}
// Abort if in Dev mode, but inject dummy functions so $gtag events don't throw errors
if (context.isDev) {
inject('gtag', () => {})
return
}
// Check if we already added script to head
let gtagScript = document.getElementById('gtag')
if (gtagScript) {
return
}
// Add script tag to head
let script = document.createElement('script')
script.async = true
script.id = 'gtag'
script.src = `https://www.googletagmanager.com/gtag/js?id=${codes[0]}`
document.head.appendChild(script)
// Include Google gtag code and inject it (so this.$gtag works in pages/components)
window.dataLayer = window.dataLayer || []
function gtag() {
dataLayer.push(arguments)
}
inject('gtag', gtag)
gtag('js', new Date())
// Add tracking codes from Vuex store
codes.forEach(code => {
gtag('config', code, {
send_page_view: false // necessary to avoid duplicated page track on first page load
})
// After each router transition, log page event to Google for each code
router.afterEach(to => {
gtag('config', code, { page_path: to.fullPath })
})
})
}
It would be great if there was a way to add the tracking IDs into this module somehow. Currently I use
nuxtServerInit
to fetch them via Apollo add them into Vuex, but I can't get them into Nuxt Config obviously.Because the tracking codes are stored in our CMS, and we like clients to be able to change them without requiring a code change from us.