Google Tag Manager callback - google-tag-manager

I have received some dataLayer definitions to place on a website. Most of them concern clicking e.g. on main menu links. But I see the following problem:
I do the dataLayer.push(some data...)
then GTM invokes AJAX hits to the connected services, like Google Analytics
but then the page reloads (this is not a SPA like angularjs site) to the new location and those hits are (in my opinion) aborted - no data is saved
I was googling some solutions but it seems that no one had such an issue - quite strange, it looks like a basic problem. Maybe GTA handles it automatically and I don't have to think about this?
Thanks for help.

GTM does not invoke AJAX (unless you put Ajax calls in custom HTML tags).
Google Analytics takes all configured tags, triggers and variables and wraps them into a huge javascript file. This file is loaded into your page and evaluated in the context of your page. If a trigger matches the respective tags are inserted into the DOM of the page. By that time there is no big difference between tags from GTM and tags that are coded into the source code of the page.
And like with hardcoded tags it does happen that hits are aborted when a page reloads. That's why GTM has a feature called "event callback", where you can pass a function that is executed only after all tags that are triggered by the event have been fired. Look at this example from the Google Analytics Enhanced E-Commerce Documentation:
function(productObj) {
dataLayer.push({
'event': 'productClick',
'ecommerce': {
'click': {
'actionField': {'list': 'Search Results'}, // Optional list property.
'products': [{
'name': productObj.name, // Name or ID is required.
'id': productObj.id,
'price': productObj.price,
'brand': productObj.brand,
'category': productObj.cat,
'variant': productObj.variant,
'position': productObj.position
}]
}
},
'eventCallback': function() {
document.location = productObj.url
}
});
Here the event callback is a function that redirects to another Url only after the tags all have been fired.
It might be wort mentioning that Google Analytics tries to avoid data loss by sending hits via the sendBeacon API (if applicable), which does not have to wait for a server response, so hits will go through even if the user navigates away from the page (however sendBeacon is not available on IE/Edge).

Related

Google Analytics Event firing too often

I have a page setup with the following GA JavaScript on the page to track pageviews
ga('create', 'UA-xxxx-xxx', 'auto');
ga('send', 'pageview', location.pathname);
I also have the following JavaScript within document.ready to track an Event
$(document).on('click', 'button[type="submit"]', function () {
if (typeof (ga) !== 'undefined') {
ga('send', 'event', 'Your Details', 'Save Address Change');
}
});
Within all development and test environments, the code fires only when it should (the form contains only ONE button) but in LIVE, the Event is almost in line with the pageview number (and the backend data confirms that the button has not been pressed as it is logged in the SQL database as it fires an INSERT statement). When I attempt to debug the JS, the event does NOT fire
Is there any way the pageview event on my form could then be triggering the event? Caching?
Using the secondary dimensions, I cannot find any data that tells me what or who is triggering this event on almost every pageview. All it confirms is that this is not isolated to one browser
The code looks like it would operate the way you would hope, so there must be something else going on... This isn't particularly an answer as much as it is other things to check that may lead to an answer:
How many Unique Events vs. Total Events are occurring for "Your Details"?
Are there any other submit buttons elsewhere on the page (search, subscribe, etc)?
Any chance you're loading your tracking script (where the event listener is) more than once?
How about spam bots? Have you noticed many server-side crawlers? This wouldn't be caused by "ghost" spambots, so check for Full Referrer as a secondary dimension.
Does this appear on both your unfiltered and filtered views?
Are any other core metrics (users, sessions, pageviews, bounce rate) in your reports odd?
Create a segment for just users who have triggered this event and look through all of your other reports. Are they following a typical funnel/path that you would expect?
Check the User Explorer to see if you can find a specific user who triggered the event. What else did they do? Does it look like a normal users?
You could add a custom dimension of Client ID and parse the GA cookie to track which CIDs are triggering the event (it would help you find them in the User Explorer).
Other custom dimensions that could help you get more context clues: Timestamp, Hit ID (random ID assigned to every individual hit), PHP Referrer.
The long shot: any chance some other script is triggering a click on that button?
I hope something here helps you.

GA / GTM Enhanced Ecommerce | Measuring Product & Product Details Impressions

I have been trying to correctly implement Google Analytics' Enhanced Ecommerce in our Shopify Store and Checkout as well as our own custom recurring checkout. And for the most part I got it working really well.
But I can't figure out how to implement Measuring Product Clicks and Measuring Views of Product Details 100% correctly as the Tag Configuration for those measurements has to be tracked as a Pageview with the trigger set to event equals gtm.dom and that causes the error "Same web property ID is tracked twice." in the Google Tag Aassistant.
I'll gladly pay for help with this if anyone would be so kind to take a look at this.
Currently on page load of our Shop 3 Tags fire.
GA Pageview
Pageview Product Impressions
Pageview Product Details Views
Which presumanly causes the aforementioned error in GTA. ("Same web property ID is tracked twice.")
How do I correctly implement Measuring Product Clicks and Measuring Views of Product Details in this case?
I alredy tried loading the regular GA Pageview on DOM Ready and set an execption for the Firing Triggers so that GA Pageview is not fired if Pageview Product Impressions or Pageview Product Details Views is fired.
But that still leaves me with 2 fired tags, which still causes the error. And also I am not positive that this is the correct way of doing it.
Please let me know if I can further explain something or improve this question somehow. Again, I am new here and I am happy to pay for help.
Been at this for 2 days 😅.
Thank you in advance for all your help and inputs! I appreciate it!
All the best,
Markus
You have two options when it comes to measuring product detail impressions:
Send the product detail impression data along with the existing page view tag that fires on this page.
Send the product detail impression data in a separate GA event tag after the page has loaded.
Which option you choose depends on whether you're able to push the product detail impression data onto the GTM dataLayer before the GTM container code or not. If you can push the product detail impression data onto the dataLayer, then you would use method (1) above. If, for whatever reason, you're not able to push the product detail impression data onto the dataLayer before the GTM container code, then you would use method (2) above.
For method (1), your code would look as follows:
dataLayer.push({
'ecommerce': {
'detail': {
'actionField': {'list': 'Apparel Gallery'}, // 'detail' actions have an optional list property.
'products': [{
'name': 'Triblend Android T-Shirt', // Name or ID is required.
'id': '12345',
'price': '15.25',
'brand': 'Google',
'category': 'Apparel',
'variant': 'Gray'
}]
}
}
});
//Your GTM container container code goes here
You when then simply setup a regular GA page view tag with trigger "All Pages" and make sure that the ecommerce option is checked in the tag configuration:
Method (1) is the recommended method but if this isn't possible for you, then method (2) would be as follows:
dataLayer.push({
'event' : 'productDetailImpression',
'ecommerce': {
'detail': {
'actionField': {'list': 'Apparel Gallery'}, // 'detail' actions have an optional list property.
'products': [{
'name': 'Triblend Android T-Shirt', // Name or ID is required.
'id': '12345',
'price': '15.25',
'brand': 'Google',
'category': 'Apparel',
'variant': 'Gray'
}]
}
}
});
As you can see, the difference here is that we have now added a custom event named productDetailImpression to the dataLayer push. The sole purpose of this custom event is to allow us to trigger a separate GA event tag in GTM whose sole responsibility is to pick up this enhanced ecommerce data and send it to GA. We achieve this as follows in GTM:
Notice the following things:
The track type of the tag is Event (not Page View)
The category and action of the event don't really matter. We're simply using this event to send enhanced ecommerce data to GA.
The ecommerce setting is enabled for this tag.
The tag has a custom event trigger defined as follows:

Google Tag Manager - Enhanced Ecommerce and ajax

In my product page detail, i have a crosselling section which loads a product list when user scroll down. I can trigger a custom event when products in this section are loads (like productsDowloaded).
How can i send product impressions with google tag manager ?
Implement the data layer following these specifications to track product impressions. If you are sending the data asynchronously, push an event to the data layer (eg: event: 'crossSellReady') and fire your custom event GA tag with a rule based on event = crossSellReady. In the custom event tag, make sure to enable enhanced eCommerce tracking, and the tag should automatically pick up the product impression data contained in the data layer. Let me know if you encounter any issue.
When the page is first loaded the first batch of cross sell products are pushed to the dataLayer as impressions and a GA pageview is sent. The GA pageview is a simple GA tag that is fired after the page is loaded.
After that, when the cross sell products are loaded asynchronously, i.e. whenever the user scrolls down, only those products are pushed to the dataLayer and a custom dataLayer event is fired in the success handler of the ajax request. For example:
// Inside Ajax success handler...
dataLayer.push({
'event': 'Custom'
'eventCategory': 'ecommerce',
'eventAction': 'ajax-load'
'eventLabel': 'cross sell'
});
You create a separate generic GA tag that sends events and is fired when the Custom event is pushed to the dataLayer. Inside the generic GA event tag you set all the of the following macros which are of type dataLayer variable:
{{event category}} -> eventCategory
{{event action}} -> eventAction
{{event label}} -> eventLabel
You can also add a nonInteraction macro in the generic GA event tag as well. Your use case, in my opinion, is considered a user interaction (user scrolled down) so the nonInteraction macro should not be set.
If you are using product lists, be careful of the positions of the cross sell items. Whenever those products are asynchronously loaded, you should note down their positions so you can track their positions in the product list tab of the GA dashboard correctly.
P.S. The generic GA event tag has multiple benefits, you can find more information about what I'm saying by reading the relevant article in Simo Ahava's blog.

Google Tag Manager (GTM) intermittently not firing in ASP

The Google Analytics / Conversions / Transactions indicate that the Tag only works sometimes - if I perform the tasks and watch what happens and/or debug it always works but when the public/others do it sometimes it works and sometimes it doesn't
The implementation is a step by step, wizard approach, Rental Car Booking. At the end of the process, we store the booking in a database, draw up a Thankyou page, firing te GTM to record the transaction in GA, and we send a confirmation email to the user.
The Setup:
GTM
Created Tag "Booking Value Transaction" - Type=Universal Analytics, Enabled Display Advert Features, Track Type = Transaction
Added 2 Rules
Rule Name = "BookNow" - Conditions {{url}} contains thankyou + {{event}} contains gtm.dom
Rule Name = "BookNow_Mobile" - Conditions {{url}} contains mobileBooking + {{event}} contains gtm.dom
ASP page
At the beginning of the
<!-- Google Tag Manager - data layer def only -->
<script>
dataLayer = [{
'transactionId': '',
'transactionTotal': 0.00}];
transactionProducts = [{
'name': '',
'sku': '',
'price': 0.00,
'quantity': 0 }];
</script>
<!-- End Google Tag Manager - data layer def only -->
Later in the page various ASP code calls database functions etc to store data and retrieve data for display and builds the data to populate the GTM datalayer
Eventually it produces the following (with appropriate values set):
<script>dataLayer = [{ 'transactionId': '1234', 'transactionTotal': 1000.00}];
transactionProducts = [{'name': 'Some Product Name', 'sku': '5678', 'price': 1000.00, 'quantity': 1 }];
dataLayer.push({'transactionProducts':transactionProducts});</script>
Following the above and before the end of the (because putting it at the top beneath the datalayer definition looked like an issue) the rest of the GTM script is inserted
<!-- Google Tag Manager -->
<% 'at the bottom of the page because the gtm.DOM async might not be performing like we want %>
<noscript><iframe src="//www.googletagmanager.com/ns.html?id=GTM-MyGTM_ID" height="0" width="0" style="display:none;visibility:hidden"></iframe></noscript>
<script>
(function(w,d,s,l,i){
w[l]=w[l]||[];
w[l].push({'gtm.start': new Date().getTime(),event:'gtm.js'});
var f=d.getElementsByTagName(s)[0],j=d.createElement(s),dl=l!='dataLayer'?'&l='+l:'';
j.async=true;
j.src='//www.googletagmanager.com/gtm.js?id='+i+dl;
f.parentNode.insertBefore(j,f);
}
)(window,document,'script','dataLayer','GTM-MyGTM_ID');
</script>
<!-- End Google Tag Manager -->
I have tried all sorts to get to the bottom of this but I am completely stumped.
How do I get this to reliably fire all the time?
The dataLayer.push() only gets the data into the dataLayer; it does not send the data to Google. You need some sort of tag that fires to carry the dataLayer data with it.
Usually this is done with the standard page view tracker, but you have to have all of the data in the dataLayer BEFORE the page view tracker fires. In a standard GTM implementation, the page view tracker fires as soon as the GTM container code is finished loading. The loading order in your thank you page should be as follows:
Declare dataLayer with all e-commerce information. Do not use
dataLayer.push(). You should have all of the necessary data to
populate dataLayer in your e-commerce system before the the page
loads. Retrieve this data and put it into dataLayer.
Load your GTM container. This is the standard code provided by GTM.
All of this should be done immediately after the <body> open tag and not at the bottom of the page code before the </body> close tag.
If you can not populate dataLayer before the GTM container code loads, then you will have to fire a GA event tag on gtm.dom to carry the transaction data.
It's likely that your inconsistent firing of the transaction data is due to the race conditions caused by improper GTM implementation.

Hashsignaling and Google Analytics

I am currently working on a site that uses hashsignaling for page loads. This means there are very few page "loads", but rather lots of ajax content changes and template manipulation.
My question is: how do I track this using Google Analytics? Is there a way I can trigger a GA call in my code that captures the entire url including the hash and any other parameters?
It depends how you want to represent your site activity in GA, but you could decide what you want to qualify as a "pageview" and call the _trackPageview() method with URL included as a parameter any time that activity happens:
_gaq.push(['_trackPageview', 'YOUR URL HERE']);
Hashsignaling fire a hashsignal.hashchange event on window object when a page is updated :
$(window).trigger('hashsignal.hashchange', [subhash]);
So you can bind a Google Analytics tracking call to this event with something like :
$(window).on('hashsignal.hashchange', function(event, subhash){
_gaq.push(['_trackPageview', subhash]);
});

Resources