vue-gtag icon indicating copy to clipboard operation
vue-gtag copied to clipboard

Track landing page view before router redirect

Open ipa1981 opened this issue 3 years ago • 10 comments

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?

ipa1981 avatar Jan 30 '22 19:01 ipa1981

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 avatar May 10 '22 14:05 sneko

@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 avatar May 10 '22 15:05 ipa1981

@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 avatar May 16 '22 07:05 sneko

@sneko sounds as a possible solution. Let's then see if @MatteoGabriele could accept this PR.

ipa1981 avatar May 16 '22 11:05 ipa1981

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.

MatteoGabriele avatar May 16 '22 18:05 MatteoGabriele

There are 2 dependencies added, they are really lightweight:

  1. mine that have a few methods to manage UTM params
  2. one to fallback if sessionStorage does 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 from and to are not deepcopies. So even in the middleware you are unable to try forcing from.page_location because the object is protected
  • some manipulation in the deepest function was independant for the page_location so 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 😄

sneko avatar May 16 '22 21:05 sneko

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.

HugoMuller avatar Jul 13 '22 08:07 HugoMuller

big +1 to figuring this out. GA is pretty much useless without the ability to identify where your traffic is coming from.

ericuldall avatar Jan 19 '23 20:01 ericuldall

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 image

ericuldall avatar Jan 19 '23 21:01 ericuldall

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

ericuldall avatar Jan 19 '23 21:01 ericuldall