This post is authored by David Vallejo. At the current juncture, this blog is not configured to support for multiple authors. I hope to remedy that in the future. ~~Yehoshua
Since Google Tag Manager was released, here at Analytics Ninja we have faced a number of problems when migrating a “hard-coded” Google Analytics implementation.
The most common problem relates to actual moment of deployment, when the old Google Analytics code has to be removed from the site. This is not much of a problem if we have access to the site and we can directly remove the hard-coded snippet at the same time you publish your new container. But let’s be real, this is not the usual scenario. We usually rely on some other company or the client’s IT department to try to synchronize the deployment. This leaves us in a challenging situation because if they remove the code and we don’t publish the container right away, some data may get lost. Or, on the other hand, if they don’t remove the code and we publish the container the hits will be sent twice. Or even worse … if we are migrating from Classic to Universal at the same time we’re moving to Google Tag Manager we could end even messing up the sessions/users/bounce rates and any other metrics/dimensions.
This problem is aggravated if we are working on a multi-domain implementation where each of the domains is being ran by different business groups… if it was hard to synchronize with one team, just imagine if there are 2 or more business groups in different time zones and having everyone required to make changes at the same time …
Even if we are able to get everyone involved in the migration, there will always be some little time gap between the code removal and the container publication.
One solution is to use a piece of code that will allow us to block all our new tags if the old code is still on the site. We will just need to schedule a date for the migration and using a simple macro and rule we’ll be just firing our new tags on the pages that have the old code already removed. This way even if there is a long timeframe to get everything sorted out, the GA data won’t be affected at all.
For this to work, we need a macro to get the current Google Analytics status on the page. For this we’ll configure in our Macro the UA property names (we’re using an array because we may have a dual tracking implementation, or the page may have a third party GA tracking and we don’t want to mess up with them). Then we’ll loop through all the trackers available to get their configured UA account, and if it matches our properties arrays we’ll return true. See following flow diagram to see what’s the macro’s logic:
The next step we need to take is to setup a new firing rule, that will allow us to block our tags if the old trackers are still on the pages.
Macro Code
We then add a blocking rule to our Google Tag Manager tags so they are not executed if any previous tracker initialized on the page.
We’ll need to keep one more thing in mind. As GA/UA code is asyncronous it may happen that Google Tag Manager tags get fired before the old code get executed, so we’ll need to delay our current tags while we’re migrating . This can be done setting the firing tag to DomReady event ( gtm.dom ), or even better for Window Load ( gtm.load ). This is not the best way to run an analytics implementation as we normally want our analytics tag to get fired ASAP, but we’ll be changing our tags firing rule to gtm.js/All Pages when we check the old code is already gone from the pages.
Let us know what you think about this implementation method in the comments section below.
Olaf Calderon says
Great article Yehoshua! it’s definitely one of those pain points when clients want to migrate. I’ve used this method for a while and it’s solid. I also built a “migration tool” which is a tag that redefines the _gaq.push method to capture any rogue Classic Analytics calls that may be left behind by accident. I grab the values pushed and send them to Universal with an option to fire a separate event indicating that this code is present.
I called my tag “Code Present Disabler” and it’s part of a whole hybrid framework I built but this particular method is a life saver for implementations involving several sites and several teams especially when the client has teams in different parts of the world –
Keep up the great work ninja!
Simo Ahava says
Great tips David!
Here are some ideas as well:
1) Check for window[‘GoogleAnalyticsObject’] instead of window.ga. This makes it more generic if someone has changed the global function name.
2) If ga.getAll() doesn’t work, it means analytics.js hasn’t yet loaded. The way to overcome this would be to tap into
window.ga.q
which is the command queue for Universal Analytics. IF analytics.js hasn’t yet loaded, it will hold an Array of Arrays with all the commands pushed into it with the ga() method. For example, you can find an Array of all the ‘create’ calls, which you can loop through to find if your UA ID has been pushed into the command queue.
Once analytics.js loads, this queue is emptied, so it won’t work anymore, but at this point ga.getAll() should work just fine.
This way you can have your tags fire upon gtm.js, since by the time the GTM library has loaded it should be near 100 % certain that AT LEAST the window.ga.q queue has been created by the Universal Analytics tracking code (since it should be before the GTM container snippet).
David Vallejo says
Hey Simo, thank you for your advice. I’ve just tried to keep the code as close as I could to usually used objects to help people understanding it. I may add an update to the post with your considerations and improvements.
Ryan Grant says
Hi David, Can you implement that code via tag manager? Or does that negate the whole point of this article?
Thanks