How do I push multiple events to google analytics on page load? - google-analytics

I'm attempting to do two pushes to the analytics datalayer when my ecommerce receipt page loads.
My issue is that I can only ever pick up one of the two events.
I'm outputting this on the receipt page:
<script>
function trackEcommerce() {
dataLayer.push({
'event': 'checkout',
'ecommerce': {
'checkout': {
'actionField': { 'step': 2 }
}
}
});
}
dataLayer.push({
'event' : 'purchaseEvent',
'ecommerce': {
'purchase': {
'actionField': {
'id': '#orderId',
'affiliation': 'Eldorado',
'revenue': '#OrderTotal.ToString("F", System.Globalization.CultureInfo.GetCultureInfo("en-GB"))',
'tax':'#VatTotal.ToString("F", System.Globalization.CultureInfo.GetCultureInfo("en-GB"))',
'shipping': '#ShippingFee.ToString("F", System.Globalization.CultureInfo.GetCultureInfo("en-GB"))'
},
'products': [
#foreach (var item in GetLoop("OrderLines"))
{
string productName = item.GetString("Ecom:Product.Name").Replace("\"", "").Trim();
string productNumber = item.GetString("Ecom:Product.Number");
double orderLineUnitPrice = item.GetDouble("Ecom:Order:OrderLine.UnitPrice.PriceWithoutVAT.Value");
int orderLineQuantity = item.GetInteger("Ecom:Order:OrderLine.Quantity");
string brand = item.GetString("Ecom:Product:Field.Brands.Value");
var DwProduct = ProductService.GetProductById(item.GetString("Ecom:Order:OrderLine.ProductID"), item.GetString("Ecom:Order:OrderLine.ProductVariantID"), item.GetString("Ecom:Product.LanguageID"));
string category = DwProduct.DefaultGroup == null ? "" : DwProduct.DefaultGroup.Name;
<text>{
'name': '#productName',
'id': '#productNumber',
'price': '#orderLineUnitPrice.ToString("F", System.Globalization.CultureInfo.GetCultureInfo("en-GB"))',
'brand': '#brand',
'category': '#category',
'quantity': #orderLineQuantity
},</text>
}
]
}
},
'eventCallback': trackEcommerce()
});
</script>
I've tried formatting this code in a variety of different ways. I've had the callback function call the second dataLayer push directly like:
'eventCallback': function () {
dataLayer.push({
'event': 'checkout',
'ecommerce': {
}
});
}
I've also attempted just outputting the two dataLayer pushes in succession with no eventCallback or other relation between the two pushes.

Most obvious thing is that you're using a function call trackEcommerce() instead of referencing a function like 'eventCallback': trackEcommerce
However, just using two plain consequent pushes should work fine and would be easier to debug.
dataLayer.push({ 'event': 'checkout', ... });
// ...
dataLayer.push({ 'event': 'purchaseEvent', ... })

Related

dataLayer.push eccomerce not appearing in GTM data Layer

I am testing setting up purchase tracking to send a data layer of purchase info to GTM. The data layer is correctly grabbing the info but for some reason I am not seeing anything when I preview GTM. As you can see in this image here I do not get the purchase event in GTM which is what my GA4 tag is set to fire on or any info from the data layer. empty GTM data-layer
Does anyone know why this is not working correctly?
<script>
window.dataLayer = window.dataLayer || [];
dataLayer.push({ 'ecommerce': null });
dataLayer.push({
'event': 'purchase',
'ecommerce': {
'purchase': {
'actionField': {
'id': xxxxxxx,
'affiliation': ,
'revenue': 40,
'tax': ,
'shipping': ,
},
'products': [
{
'id': xx-xx,
'name': xxxxxxx,
'category': xxxxxxx,
'price': 40,
'quantity': 1 },
]
}
},
'user_data': {
'email': test#gmail.com,
'phone_number': 7777777777,
'address': {
'first_name': Test,
'last_name': Test,
'street': 123 test st,
'city': test23,
'region': WV,
'postal_code': 12345,,
'country': US,,
}
}
});
</script>

Creating a product array for Google Analytics ecommerce via GTM

I have the following function to pass items from a shopping cart into the data layer and then on to Google Analytics through GTM.
No problem with the variables, those are all populating fine. It's how I've tried to create the products array, it's not done correctly. If I have more than one product in the cart, only the first product gets passed into the data layer.
You'll notice two events: sendTransaction and sendUpsell. That's because there's an option in the shopping cart to also make a personal donation on top of the products you're purchasing which gets added to the total transaction amount.
function eCommerceTracker(){
var storeId = "store_id";
var personalGift = $('p#additional_donation').text().replace("$","").replace(/[,]/g, "").trim();
var trackingCode = $('span#tracking_code').text().trim();
var numItems = $("div.ShoppingCart [class*='ShoppingCartRow']").length;
eQuantity = [];
transTotal = [];
itemName = [];
$("div.ShoppingCart [class*='ShoppingCartRow']").each(function(){
eQuantity.push($(this).find("div.quantity-column").text().trim());
itemName.push($(this).find("span.CartItemName").text().replace("'",""));
transTotal.push($(this).find("div.price-column").text().replace("$","").replace(/[,]/g, "").trim());
});
eTotal = $("div.ShoppingCart div.total-price-column:last").text().replace("$","").replace(/[,]/g, "").trim();
for (var i = 0; i < numItems; i++) {
if(eQuantity[i] > 0){
dataLayer.push({
'event': 'sendTransaction',
'ecommerce': {
'purchase': {
'actionField': {
'id': trackingCode,
'affiliation': storeId,
'revenue': eTotal
},
'products': [{
'id': trackingCode,
'name': itemName,
'category': 'eCommerce',
'price': transTotal,
'brand': 'myBrand',
'quantity': eQuantity
}]
}
}
});
}
}
//Adding personal gift
if(personalGift){
dataLayer.push({
'event': 'sendUpsell',
'ecommerce': {
'purchase': {
'actionField': {
'id': trackingCode,
'affiliation': storeId,
'revenue': personalGift
},
'products': [{
'id': trackingCode,
'name': 'Personal Gift',
'category': 'Upsell',
'price': personalGift,
'brand': 'myBrand',
'quantity': '1'
}]
}
}
});
}
}
Does anything look immediately wrong with what I've created here?

Questions on a manual implementation of Enhanced Ecommerce

I'm (trying) to implement Enhanced Analytics on an aspx/mvc website.
First, I set up a UA Tag triggering off the custom event "checkout":
Tag Type: Universal Analytics
Track Type: Event
Event Action: Checkout
Enable Enhanced Ecommerce Features: true
Use Data Layer: true
Then, I created a Custom HTML tag to push the checkout event to the Data Layer; firing off of Window Load of the checkout URL. the custom HTML is:
<script type='text/javascript'>
(function() {
dataLayer.push({
'event': 'checkout',
'ecommerce': {
'checkout': {
'actionField': { 'step': '1' },
'products': [{
'name': 'product1',
'id': '123456',
'price': '500',
'dimension2': 'Acccepted',
'dimension5': '12345'
}]
}
}
});
})
</script>
GTM preview shows the custom html tag firing but the associated UA Event tag does not fire.
Help?
You have a small mistake in your JS. You forgot to call defined function (pay attention at () at the end):
(function() {
dataLayer.push({
'event': 'checkout',
'ecommerce': {
'checkout': {
'actionField': { 'step': '1' },
'products': [{
'name': 'product1',
'id': '123456',
'price': '500',
'dimension2': 'Acccepted',
'dimension5': '12345'
}]
}
}
});
}())

fullcalendar - multiple sources to turn off and on

I've a calendar that I want to list various types of event on and enable a checkbox filter to show/hide those kind of events.
Is there a way to say on this action, ONLY load from 1 data-source AND remember that URL on month next/prev links?
I've started using eventSources, but it loads them all, rather than the one(s) I want.. Here's what I have.
var fcSources = {
all: {
url: tournament_url + '/getCalendar/?typefilter=[1,2]'
},
type1: {
url: tournament_url + '/getCalendar/?typefilter=[1]'
},
type2: {
url: tournament_url + '/getCalendar/?typefilter=[2]'
}
};
These URLS all provide a json string of events, based on the types prrovided.
Here's my calendar:
$('#calendar').fullCalendar({
header: {
left: 'prev,next today',
center: 'title',
right: 'month,basicWeek'
},
firstDay: 1, // Monday = 1
defaultDate: new Date(), // Now
editable: true,
eventSources: [ fcSources.all ],
events: fcSources.all,
nextDayThreshold: '00:00:00',
... etc etc
Above my calendar I have this:
input type="checkbox" name="event_filter[]" value="type1" /> Type 1
input type="checkbox" name="event_filter[]" value="type2" /> Type 2
And finally , two Jquery fucntions.. one to get all the filters:
function getFilters(getName) {
var filters = [];
var checked = [];
$("input[name='"+getName+"[]']").each(function () {
filters.push( $(this).val() );
});
$("input[name='"+getName+"[]']:checked").each(function () {
checked.push( $(this).val() );
});
return [filters, checked];
}
and the last to load them:
$(".event_filter").on('click', function() {
var doFilters = getFilters('event_filter');
$('#calendar').fullCalendar( 'removeEvents' );
if (doFilters[0] === doFilters[1]) {
$('#calendar').fullCalendar( 'addEventSource', fcSources.all );
} else {
$.each(doFilters[1], function(myFilter, myVal) {
console.log(myVal);
$('#calendar').fullCalendar( 'addEventSource', fcSources.myVal );
});
}
// $('#calendar').fullCalendar( 'refetchEvents' );
});
Since the sources are all the same place and just different data on the URL, this approach could meet your needs. In the demo it just alerts the URL that is being tried but doesn't actually supply any data...
https://jsfiddle.net/gzbrc2h6/1/
var tournament_url = 'https://www.example.com/'
$('#calendar').fullCalendar({
events: {
url: tournament_url + '/getCalendar/',
data: function() {
var vals = [];
// Are the [ and ] needed in the url? If not, remove them here
// This could (should!) also be set to all input[name='event_filter[]'] val's instead of hard-coded...
var filterVal = '[1,2]';
$('input[name="event_filter[]"]:checked').each(function() {
vals.push($(this).val());
});
if (vals.length) {
filterVal = '[' + vals.join(',') + ']' // Are the [ and ] needed in the url? If not, remove here too
}
return {
typefilter: filterVal
};
},
beforeSend: function(jqXHR, settings) {
alert(unescape(settings.url));
}
}
});
// when they change the checkboxes, refresh calendar
$('input[name="event_filter[]"]').on('change', function() {
$('#calendar').fullCalendar('refetchEvents');
});
Try this!
$('#calendar').fullCalendar({
events: function( start, end, timezone, callback ) {
var checked = [];
$("input[name='event_filter[]']:checked").each(function () {
checked.push( $(this).val() );
});
var tournament_url = 'https://www.example.com';
$.ajax({
url: tournament_url + '/getCalendar/',
data: {typefilter: '['+checked.join(',')+']'},
success: function(events) {
callback(events);
}
});
}
});
$('input[name="event_filter[]"]').on('change', function() {
$('#calendar').fullCalendar('refetchEvents');
});
This works for me.

Meteor pub/sub issues

This below is my collection code
Competitions = new Mongo.Collection("competitions");
var CompetitionsSchema = new SimpleSchema({
year: {
type: String
},
division: {
type : String,
allowedValues: ['Elite', '1st','2nd','3rd','4th','Intro']
},
teams:{
type : [TeamSchema],
allowedValues: (function () {
return Teams.find().fetch().map(function (doc) {
return doc.name;
});
}()) //here we wrap the function as expression and invoke it
}
});
In the allowedValues function
Teams.find is empty.
In the router I am subscribing to the publication as follows
this.route('competitions', {
path: '/admin/competitions',
layoutTemplate: 'adminLayout',
waitOn: function () {
return [
Meteor.subscribe('teams')
];
}
});
This is my publish function
Meteor.publish('teams', function() {
return Teams.find({},{sort: {
points: -1,
netRunRate : -1
}});
});
Do I have to do subscription some where else as well?
Your problem is in this piece of code:
allowedValues: (function () {
return Teams.find().fetch().map(function (doc) {
return doc.name;
});
}()) //here we wrap the function as expression and invoke it
This gets called when the page loads. At that point the Teams collection will still be empty on the client side. You need to wait until the data is ready. Since you are using waitOn in iron-router, it might be enough to just move this code to the onRendered callback.

Resources