vue-gtag
vue-gtag copied to clipboard
Track landing page view before router redirect
In our app we have router redirect to sign in page if user's auth token has expired. If we want additionally track UTM parameters (utm_source, utm_medium, etc), we pass it in the URL. For example:
/dashboard?utm_source=push&utm_medium=welcome
If a user is signed in, the VueGtag takes this URL with utm_* params and tracks them correctly. If a user is not signed in and we redirect it immediately to /sign-up, and it tracks the latter URL. Probably to the race condition.
Of course possible solutions are:
- Pass utm_* params to redirected URL. However there is not the only such case and dragging querystring through all redirects is a bit ugly in a large app.
- Wait for the tracking event to happen and redirect then. We tried:
Vue.use(VueGtag, {
config: { id: "..." },
onAfterTrack () {
redirectNow()
}
}, router)
But for some reason onAfterTrack() is never called (vue-gtag version 1.16.1). Moreover it's not clear if it is called always. For example when adblocker is active, or what if there is a network latency or Analytics service down.
If there any recommendation how to handle such race conditions in a best way or do we miss something?
Hi @ipa1981 ,
Did you find a solution? I'm in almost the same case:
- If a redirect happens I still want gtag.js to track the UTM parameters
- I don't want to keep UTM parameters a few milliseconds after the page is loaded, because there is a risk the user would copy/paste this link on another media (breaking the whole thing of UTM parameters)
I think that's possible by catching the original URL before the router is ready and running. You could get UTM parameters, then we should push them manually to Google Analytics (maybe through a specific set()...), and then we could remove them from the current route (either by stripping them before the router acts, or by using a router.replace({ query: allCurrentParamsWithoutUTMOnes }).
The hard part for now is how to explicitly pass them to gtag.js... need to have a look.
Any thought @MatteoGabriele ?
@sneko nope. We didn't find a solution, nor anyone gave any suggestions here as you may notice. So still live with some visits get untracked :)
@ipa1981 in case you still want to solve this issue I worked on a third-party library (https://github.com/sneko/utm-synapse) that I integrated into vue-gtag. Please see https://github.com/MatteoGabriele/vue-gtag/pull/445 for details 👍
PS: about your wondering on onAfterTrack(), this one is not called for the first track, just for subsequent ones (see https://github.com/MatteoGabriele/vue-gtag/blob/8c2e39555fb867a38251ca48c6011256603df69d/src/add-routes-tracker.js#L18-L47).
@sneko sounds as a possible solution. Let's then see if @MatteoGabriele could accept this PR.
I'm sorry for texting you back so late. I checked the PR that @sneko opened but adding multiple dependencies to handle the UTM tag only seems too much for me. I will try to learn more about it and check how to proceed.
There are 2 dependencies added, they are really lightweight:
- mine that have a few methods to manage UTM params
- one to fallback if
sessionStoragedoes not exist
I could have for sure implemented methods directly in your library for (1), but it's not scoped to Vue, nor gtag. And for the (2), I could have tried to reinvent the wheel to fallback this, but for me using tested and working librairies is fine too. But I do understand your point it can be a nightmare when having XXXX deps.
To be honest, at first I wanted to not fork your repo just by using the middlewares, so the user could use in addition my library to manage UTM params. But:
- they are not consistent between the init and for each router event
- the parameters passed into it
fromandtoare not deepcopies. So even in the middleware you are unable to try forcingfrom.page_locationbecause the object is protected - some manipulation in the deepest function was independant for the
page_locationso unmanageable from the middlewares
But if you find how to arrange this to make it the way the library is, there is no problem for me 😄
Hi,
@MatteoGabriele is there any reason why the hooks onBeforeTrack() and onAfterTrack()are not called on the landing page (first track)? They could be called at least with the current route, like track.
big +1 to figuring this out. GA is pretty much useless without the ability to identify where your traffic is coming from.
Would the following documentation:
gtag('set', 'campaign', {
'id': 'abc.123',
'source': 'google',
'medium': 'cpc',
'name': 'spring_sale',
'term': 'running+shoes',
'content': 'logolink'
});
Be implemented in api/pageview as:
event('set', 'campaign', {})
Is that correct?
If so could be pretty simply passed through from track.js
const { query } = to;
let utm = {};
for (let key in query) {
if (key.match(/^utm\_/)) {
utm[key.split('_')[1].replace('campaign', 'id')] = query[key];
}
}
if (Object.keys(utm).length) {
// we have utm params, let's save them in local storage
localStorage.setItem('vue_gtag_utm', JSON.stringify(utm));
} else {
// we don't have utm params, let's check local storage
utm = JSON.parse(localStorage.getItem('vue_gtag_utm') || '{}');
}
api.pageview(template, utm);
I'm testing this on my end, but want to make sure the event is what I think it is.
UPDATE Seems to work well it's adding the utm params to the page_view request

Sent a PR, any feedback is appreciated: https://github.com/MatteoGabriele/vue-gtag/pull/517