I have a wordpress/woocommerce website which uses the GTM4WP plugin to send the website data to the GTM datalayer. In GTM I have successfully setup a purchase event which sends all data to the GA4 interface. So far so good.
Now there are two items (ID 224112 and 159324) on my website for which I do NOT want to see the revenue in my GA4 account. (The fact that they trigger a purchase event is not so much the problem but the revenue value should be ZERO.)
I have been searching for hours and found out I can do a custom Javascript function which should do the trick. Except I'm not very skilled with Javascript...
This is the instruction I found:
//This field should be a JavaScript function that returns a value using the 'return' statement.
//If the function does not explicitly return a value, it will return undefined and your container may not behave as expected.
//Below is an example of this field:
function() {
var now = new Date();
return now.getTime();
}
The value of both of these items can be different, I also run a multicurrency website, so the only thing we can go by is the ID.
When I do a test-purchase through the GTM preview mode I can see the following values in the data layer of the purchase event (I XXXed out a few things which are not needed here):
{
event: "purchase",
gtm: {uniqueEventId: 11, start: 1654376017109},
visitorLoginState: "logged-in",
visitorType: "XXX",
pagePostType: "page",
pagePostType2: "single-page",
browserName: "Chrome",
browserVersion: "102.0.5005.61",
browserEngineName: "Blink",
browserEngineVersion: "",
deviceType: "desktop",
deviceManufacturer: "Apple",
deviceModel: "Macintosh",
cartContent: {
totals: {
applied_coupons: [],
discount_total: 0,
subtotal: 0,
total: 0
},
items: []
},
orderData: {
attributes: {
date: "2022-06-04T22:53:18+00:00",
order_number: "226813",
order_key: "wc_order_Z6HrzhCqQ3pTS",
payment_method: "pensopay",
payment_method_title: "Credit/Debit card",
shipping_method: "3-5 days",
status: "processing",
coupons: ""
},
totals: {
currency: "DKK",
discount_total: "0",
discount_tax: "0",
shipping_total: "40",
shipping_tax: "0",
cart_tax: "0",
total: "90.00",
total_tax: "0",
total_discount: "0",
subtotal: "50",
tax_totals: []
},
customer: {
id: 3,
billing: {
first_name: "XXX",
last_name: "XXX",
company: "",
address_1: "XXX",
address_2: "",
city: "XXX",
state: "",
postcode: "XXX",
country: "DK",
email: "XXX",
emailhash: "dafb4416fe8aa737d5b09733b4d3310f6ca31276bebe6dd24" +
"bcbe1651fe4abde",
phone: "XXX"
},
shipping: {
first_name: "XXX",
last_name: "XXX",
company: "",
address_1: "XXX",
address_2: "",
city: "XXX",
state: "",
postcode: "XXX",
country: "DK"
}
},
items: [
{
id: 224112,
name: "Materials",
sku: 224112,
category: "XXX",
price: 50,
stocklevel: null,
brand: "XXX",
quantity: 1
}
]
},
new_customer: false,
ecommerce: {
currencyCode: "DKK",
purchase: {
actionField: {
id: "226813",
affiliation: "",
revenue: 90,
tax: 0,
shipping: 40,
coupon: ""
},
products: [
{
id: 224112,
name: "Materials",
sku: 224112,
category: "XXX",
price: 50,
stocklevel: null,
brand: "XXX",
quantity: 1
}
]
},
currency: "DKK",
items: [
{
item_id: 224112,
item_name: "Materials",
item_brand: "XXX",
price: 50,
item_category: "XXX",
quantity: 1,
google_business_vertical: "retail",
id: "224112"
}
],
transaction_id: "226813",
affiliation: "",
value: 90,
tax: 0,
shipping: 40,
coupon: ""
}
}
Well, it would be best to first not allow things that you don't want to have in DL. Since you just use plugins, then I would suggest to either make a change in the plugin logic to ignore specified products, or change the data. Just set the price for those products to the appropriate values.
Another approach to it would be through GA reporting. Just exclude the product ids you're not interested in from the reports.
I suggest these approaches because this is not a GTM issue really. Fixing this through GTM would be a hack and we try to avoid hacks in production.
Now that we went through that, yes, there are a few ways to fix it through GTM. An obvious one would be just to add a CJS blocker to your EEC trigger that would check if these products are in the ecommerce object and block the thing from firing if they're there. But this means blocking it for any other products that may be tracked in the same call.
You can also rebuild the whole ecommerce object with a CJS variable, the detailed explanation can be found here: https://www.simoahava.com/analytics/enhanced-ecommerce-with-a-custom-javascript-variable/ in case you're using Universal Analytics.
There's a similar solution for GA4. A simpler one. In GA4, you override your DL EEC push by just setting an event parameter for your EEC tag that sets the items property. You would use a CJS as a value. In your CJS you should return a proper array of items by taking what's in the DL and sanitizing it.
Related
I'm trying to create a dataLayer variable so I can push the product name into the event label.
The dataLayer push when a user adds a product to cart is:
{
event: "addToCart",
gtm: {
uniqueEventId: 107,
start: 1666871102469,
scrollThreshold: 75,
scrollUnits: "percent",
scrollDirection: "vertical",
triggers: "30151582_46"
},
customer_id: "4cfa14bf-1749-47a3-9063-e19c0bc6f3a8",
ecommerce: {
currencyCode: "NZD",
add: {
products: [
{
name: "Panadol Rapid Soluble Tablets - Packet 20",
id: "FAH262",
price: 12.28,
brand: "Panadol",
category: "Web / Dental / Consumables / Anaesthetics / Pain" +
" Relief",
variant: "",
quantity: 1
}
]
}
}
}
I've tried to create a dataLayer variable with the following
ecommerce.add.products[0].name
This is returning undefined in preview mode when I do test add to carts.
Where am I going wrong?
You might need to change the DataLayer variable to
I can't really remember where I saw about this.
But when fetching data through here.
It is not regular get products[0].name but products.0.name
Due to some unknown reasons, our mongodb data was completely removed. Our db was hosted on azure but even they couldn't help. But luckily, I have a backup but its in the following format.
{
_id: new ObjectId("626db76647f188002d4cba05"),
phoneNumber: null,
address: "",
city: "",
country: "",
zipcode: "",
houseNumber: "",
additionalInfo: "",
isEmailVerified: false,
isPaymentDone: false,
isIDVerified: false,
isEmailConfirmed: false,
email: "testnutest#gmail.test",
password: "$2a$10$XC0fZ.Yw19Bn1e6DbY4IuO8RDHrvECEPU/bSk2jFM6jXB.H10penW",
createdAt: 2022-04-30T22:25:42.716Z,
updatedAt: 2022-05-01T20:03:13.232Z,
__v: 0,
emailVerification: {
emailVerificationToken: "Token String",
expires: "2022-05-02T14:25:43.098Z"
}
},{
_id: new ObjectId("626db7c147f188002d4cba10"),
phoneNumber: null,
address: "",
city: "",
country: "",
zipcode: "",
houseNumber: "",
additionalInfo: "",
isEmailVerified: false,
isPaymentDone: false,
isIDVerified: false,
isEmailConfirmed: false,
email: "maybe#testing.dj",
password: "$2a$10$k6Z.IMRv.MhotvuY37cDHuCBF/qsspJqYx7hx6XcGHuws9.9QfR.2",
createdAt: 2022-04-30T22:27:13.988Z,
updatedAt: 2022-05-01T20:03:15.677Z,
__v: 0,
emailVerification: {
emailVerificationToken: "Token String",
expires: "2022-05-02T14:27:14.426Z"
}
}
As this is a lot of data. Some of the common issues are following
First of the keys are not double quoted.
Secondly, the value _id starts with "new ObjectId" function which cannot be converted to proper json format.
There are timestamps called "createdAt:" and "updatedAt:", the values of these timestamps contain colon ":", which cannot be processed properly.
If there is any regex or a script that someone can provide, I will be really helpful. I have tried in javascript but couldnt get it done.
I have a JSON data with something like this,
{
applylink: "https://www.techgig.com/jobs/Senior-Knowledge-Analyst-CKA/59843",
companyname: "Boston Consultancy Group",
created: "",
enddate: "",
experience: "4-6 yrs",
jd: "",
location: "Bengaluru/Bangalore",
salary: "",
skills: "cassandra",
source: "techgig",
startdate: "",
timestamp: 1528959791.958316,
title: "Senior Knowledge Analyst CKA",
type: ""
}
I want to query it with multiple key values like
var query = {
skills: [],
location: ["Bengaluru/Bangalore","Pune"],
experience: ["4-6 yrs"]
};
This is the function which I sought to write, there were a few ans regarding this, but I was unable to understand them,
function find_in_object(my_array, my_criteria) {
}
How should I write this function so that, I can implement this feature
Thanks
Edit 1:
Able to make something like this:
function find_in_object(my_array, my_criteria) {
var x = my_array.map((data)=>{
var filter=[];
var keys = Object.keys(query);
keys.map((imf)=>{
if(query.imf.indexOf(data.imf)){
}
})
})
A straight-forward and performant (in most cases) approach is to iterate the entries of the query, looking at each corresponding prop in the objects being searched. Fail aggressively if any aspect of the query doesn't match.
There's no getting around iterating all of the input data to test for match, nor can we avoid iterating all props in the query until a mismatch. One place to improve speed is in array.includes() (by better indexing those arrays), but I'd test this for acceptable performance first.
let data = [{
applylink: "https://www.techgig.com/jobs/Senior-Knowledge-Analyst-CKA/59843",
companyname: "Boston Consultancy Group",
created: "",
enddate: "",
experience: "4-6 yrs",
jd: "",
location: "Bengaluru/Bangalore",
salary: "",
skills: "cassandra",
source: "techgig",
startdate: "",
timestamp: 1528959791.958316,
title: "Senior Knowledge Analyst CKA",
type: ""
},
{
applylink: "some other link",
companyname: "Acme Inc",
created: "",
enddate: "",
experience: "6-8 yrs",
jd: "",
location: "Pittsburg",
salary: "",
skills: "javascript",
source: "techgig",
startdate: "",
timestamp: 1528959791.958316,
title: "Senior Knowledge Analyst CKA",
type: ""
}
]
// matches the first job
let query1 = {
location: ["Bengaluru/Bangalore", "Pune"],
experience: ["4-6 yrs"]
};
// matches the second job
let query2 = {
location: ["London", "Pittsburg"],
experience: ["6-8 yrs"]
};
// matches neither
let query3 = {
location: ["Bengaluru/Bangalore", "Pune"],
experience: ["6-8 yrs"]
};
function dataMatchingQuery(data, query) {
return data.filter(datum => datumMatchesQuery(datum, query))
}
// true if the datum's values can be found in the query arrays for every prop
function datumMatchesQuery(datum, query) {
for (let [k, v] of Object.entries(query)) {
if (!v.includes(datum[k])) return false
}
return true
}
console.log(dataMatchingQuery(data, query1))
console.log(dataMatchingQuery(data, query2))
console.log(dataMatchingQuery(data, query3))
Please, consider the following example:
https://codepen.io/anon/pen/aadBGJ?editors=1111
I'm trying to read the table into the JS object, but somehow it only stores the last line.
I get:
{
ean: "test3",
sku: "0003"
}
I want to get:
[
{
ean: "test1",
sku: "0001"
},
{
ean: "test2",
sku: "0002"
},
{
ean: "test3",
sku: "0003"
},
]
Your input is very much appreciated, thank you!
Solution found (credits to https://gist.github.com/WickyNilliams/9252235#file-parsetable-js). I updated the codepen.
I've got some data stored this way:
var protossUnitsArray =
[
{ name: "Zealot", health:"100", shield:"50", armor:"1", picture: "/images/protoss/zealotPortrait.png" },
{ name: "Stalker", health: "80", shield: "80", armor: "1", picture: "/images/protoss/stalkerPortrait.png" },
{ name: "Sentry", health: "40", shield: "40", armor: "1", picture: "/images/protoss/sentryPortrait.png" },
{ name: "High Templar", health: "40", shield: "40", armor: "0", picture: "/images/protoss/hightemplarPortrait.png" },
{ name: "Dark Templar", health: "40", shield: "80", armor: "1", picture: "/images/protoss/darktemplarPortrait.png" },
{ name: "Immortal", health: "200", shield: "100", armor: "1", picture: "/images/protoss/immortalPortrait.png" }
];
var protossUnitsList = new WinJS.Binding.List(protossUnitsArray);
var publicMembers =
{
itemList: protossUnitsList
};
WinJS.Namespace.define("ProtossUnitsData", publicMembers);
As you can see, the array has been made publicly available.
How do I actually reference data from this array from another javascript file?
Let's say I want to know what a Stalker's health is (which is 80). Let's assume I know Stalkers are always going to be the second item in the array, shouldn't it be something like
ProtossUnitsData.itemList[1]['health'] ?
But that's not quite right..
If you want to access 2nd item from the array protossUnitsArray, shouldn't it be:
protossUnitsArray[1].health
I don't know about Windows 8 and the UI formerly known as Metro, but in JavaScript shouldn't it just be:
ProtossUnitsData.itemList[1].health
Edit
Looking at the documentation, it seems that WinJS.Binding.List exposes methods for working with the data in the List. See here and here for more info, but it looks like you want to use:
var item = ProtossUnitsData.getItem(1),
data = item.health;
That might work...
Figured it out! It's actually:
ProtossUnitsData.itemList.getAt(1).health;