GA4 currently provides two methods for tracking. They are gtag and GTM (dataLayer).
The gtag method does NOT require the ecommerce property but the dataLayer method does.
Example:
gtag("event", "add_payment_info", {
items: [
{
// item's properties
}
]
});
dataLayer.push({
event: "add_payment_info",
ecommerce: {
items: [
{
// item's properties
}
]
}
});
Is there any difference between the two methods?
I understand that gtag will call dataLayer.push under the hood. But is there any technical reason that the ecommerce property is required for GTM methods or is it just by design?
Use DataLayer as much as you can. Because it can be highly re-use in the Google Tag Mangaer.
The common marketing technology now is not only GA to implement. There are also like Facebook pixel and a lot of pixels that need to be installed.
Most of them has similar Ecommerce feature like view_item add_to_cart purchase.
If you use DataLayer. You can just use the items in it and re-assemble to another pixel need.
If you use gtag. This function will only apply on GA and Google Ads. In the future you still need to implement facebook pixel again from begining.
So the point here is once there is a accurate DataLayer on the website. It will save times in the future.
Related
We are currently experimenting with Google Tag Manager. Beside couple of small pixels we want to include Google Analytics 4.
According to the documentation we need to include the tag "Google Analytics: GA4 Configuration" which inserts gtag.js into the page. This means that we have two containers on a single page.
We have multiple events that are fired on click of a button. After the events are fired we want to navigate the user to a different page. To ensure that all tags are fired before we navigate to a different page we use the provided eventCallback method.
dataLayer.push({
event: 'add_to_cart',
...
eventCallback: function(containerId, eventInformation) {
...
},
});
However, due to the fact that we have two containers embedded the eventCallback is fired twice (one time for each container).
How can we know/guarantee that all containers finished firing? So far I've seen that people suggest to check if a specific container is finished (https://support.google.com/optimize/thread/3463880/optimize-firing-multiple-pageviews-and-eventcallbacks-when-implemented-through-tag-manager?hl=en) but that doesn't look like a feasible solution to me, because the order in which the containers finished is not guaranteed.
An alternative approach would be to count the number of containers that have already fired, but that would require to hardcode the number of available containers.
To me it seems like there must be a better solution than the approve described approaches. Does anybody have experience with it? Are there any best practices?
For me all events in the page were already built for GTM, and GTM Handels triggering events to GA4 & UA. So I only needed the callback for GTM. Before adding the blow solution to my code the callbacks were firing twice causing multiple issues. My solution:
const buildGtmCallback = (callback) => {
//GA4 is also a container, so need to fire callbacks only once, for GTM container
//GA4 containerId starts with G-
return (containerId) => {
if (containerId.startsWith("GTM-") && typeof callback === "function") {
callback();
}
}
}
And then whatever you wish to be fired only once:
window.dataLayer.push({
'event': 'add_expense',
'eventCallback': buildGtmCallback(() => {
console.log('Call me only once');
})
});
And as I mentioned - the code fires event to GTM, which (if needed) will fire those to GA4, UA or whatever is defined. According to google docs “eventCallback” is called after all of those were called so I found this solution to work without issues
When navigating around in my SPA, I'm firing VirtualPageView events, but this is what the Google Analytics debugger spits out:
It seems to be recreating the Google Analytics tag over and over. I'm not a GA expert, but from what I read, this is really bad for proper analysis. I think it has something to do with restarting the user session over and over?
The Google Tag Assistant seems to think the GTM itself is being recreated:
Things seem fine in the GTM preview console:
To emphasize my concern: The GA tag/tracker seems to be repeatedly recreated. Am I right? If so, how do I fix it?
For a reference, here's what I got configured in GTM:
The key functions that handle GTM events in my app are as follows:
const sendEvent = ({event, eventCategory, eventAction, eventLabel}: GtmEvent): void =>
send({
event,
eventCategory,
eventAction,
eventLabel,
nonInteraction: false
});
const sendVirtualPageView = (data: { url: string, title: string }): void =>
send({
event: <'VirtualPageView'>'VirtualPageView',
virtualPageURL: data.url,
virtualPageTitle: data.title,
});
const send = (data: GtmEvent | VirtualPageView): void =>
window.gtm.push(data);
GTM creates a new instance of the tracker object with a random name for every hit. While I do not have any official information I assume that is done to avoid hit scoped custom dimensions and other settings being automatically propagated to all GA tags, if you want them to or not (i.e. you might want to send different information for pageview tags and event tags). Also this avoids trackers overwriting each other if you track to more than one GA account.
If you want to have settings shared between GA tags you can now use the settings variable, and set anything specific to a tag directly in the tag settings.
So what you are seeing in the debugger just means that GTM is working as expected. as for Tag Assistant, while this is a potentially useful tool it gives an awful lot of false alarms, so use it with some caution.
I am making the change from the basic analytics code to google tag manager since I need it to track impressions for certain elements. While testing when the pageview fires, I get this warning :
"This page took a long time to send a pageview hit to Google Analytics. Users could be clicking away from your site before it records a pageview."
Google tag manager requires adding the code at the beginning of the body (I tried adding it in the header just in case it helps with that warning, but that didn't work).
Probably GA is not the best choice for such task. GA is well-tailored for pageviews, but not for custom actions.
I solve similar issue with http://www.devmetrics.io analytics. To track impressions for certain elements on my page: 1) add for each of this elements trackvisible css class 2) using setInterval check visibility every few seconds.
Example code using jQuery and devmetrics analytics:
$('.trackvisible').each(function( index ) {
if ($(this).visible()) {
var tag = 'element.' + $(this).attr('id');
devmetrics.userEvent('impression', [tag]);
}
});
We're having some issues when we're loading an iframe with a video player that sends playback Events to Google Universal Analytics (analytics.js) loaded inside that iframe (on another domain). The GA tracker is not being loaded on iOS devices and because of that, no event tracking is being sent to GA.
On Android and other devices including desktop it works just fine, but not on iOS unless I changed the third-party cookies setting that comes default on iOS Safari.
I did a test using a cookie-less method for Google Analytics (https://github.com/Foture/cookieless-google-analytics) and that way iOS devices were able to correctly send track Events to GA. However, I want to use that method only as a fallback when the regular GA method don't work, because the UserId that is created via the Fingerprint method is not very unique on mobile devices.
So I need a way to detect when the regular GA method is able to track events and if is not able, either because the tracker was not loaded or cookies are disabled, then use the cookie-less method to load GA and track the events.
Thanks!
You should use check JavaScript window.ga && ga.loaded variables before using ga() method to track events:
if(window.ga && ga.loaded) { {
// if yes, rely on GA to follow link
ga('send', 'event', 'outbound', 'click', url, {
'transport': 'beacon',
'hitCallback': function(){document.location = url;}
});
} else {
// if not, follow link ourselves
document.location = url;
}
Se more on https://hacks.mozilla.org/2016/01/google-analytics-privacy-and-event-tracking/
You could try using a (seemingly) undocumented property on the ga object: ga.loaded.
The only reference to this property I could find in the official documentation is in an example describing the use of hitCallback for E-Commerce tracking:
// Called when a link to a product is clicked.
function onProductClick() {
// Truncated Google Analytics example for brevity.
// [...]
}
Android Warhol T-Shirt
You could thus try something similar to:
if (typeof ga !== 'undefined' && ga.hasOwnProperty('loaded') && ga.loaded === true) {
// ga successfully loaded. Custom Events available
// ...
} else {
// ga not loaded, fallback to another tracking implementation.
// ...
}
I am looking for some clues on where to add Google Analytics Event Tracking to a page that has AnythingSlider installed. I have a slider that does not autoscroll and you have to click the navigation buttons for the slides to move. I wish to track these clicks. I would also like to track if a visitor clicks on a link within a slide.
I am wishing to use Google's InPage Analytics to track visitor click behavior and workout what items (images & phrases) catch the attention of the visitor in order to make better lead funnels.
I did try the Event tracking guide from Google before posting here, but I was unsure of where to pickup the navigation clicks from the slider.
add this to any a href in your html
onClick="_gaq.push(['_trackEvent', 'Slider','Panelno:x', 'blah']);"
Untested (I'm about to do this myself) but the API suggests to me that I should use the onSlideComplete callback, e.g. (assuming you've set up the names of your panels in an array called pages).
onSlideComplete : function(foo) {
_gaq.push(['_trackEvent', 'Slider','Panelno:'+slider.currentPage, pages[index - 1]]);
}
EDIT: Be careful with onSlideComplete, it seems to fire off too often. Set a var to tell it not to refire, and reset the var with onSlideBegin.
onSlideBegin : function(e, slider) {
refire = 1;
},
onSlideComplete : function(slider) {
if (refire) {
_gaq.push(['_trackEvent', 'Slider','Panelno:'+slider.currentPage, pages[slider.currentPage - 1]]);
refire=0;
}
}