I have a datalayer variable for a category on a page. I've got this firing correctly however the values within this variable can be multiple categories and therefore presented as a comma separated list:
dataLayer = [{
'storeCategory': 'major store', 'food', 'childrenswear', 'health & beauty'
}];
What I would like to do is fire a GA event for each and every catgeory in the list:
Event catgeory: "Store"
Event action: "ViewCategory"
Event label: {storeCategory value}
I have a feeling I need to use a custom JavaScript variable to parse the list but not sure how this links in with triggers or tags.
Your dataLayer is incorrect, the 'storeCategory' variable should be an array, I think you're just missing the brackets.
I'm not sure how much help you need, but essentially you need to:
Create a datalayer variable to capture the storeCategory array.
Create a custom html tag that fires on "all pages" to loop through the storeCategory array, like so:
.
<script>
var cats = {{store category}};
var catLen = cats.length;
for (var i = 0; i < catLen; i++){
dataLayer.push({
'event': 'category-view',
'category':cats[i]
});
}
</script>
Create another datalayer variable to capture the "category" variable from step 2.
Create a custom event trigger to trigger on "category-view" or whatever you name it.
Create a GA event tag and capture the "category" variable in the "label", make sure you set it to non-interaction.
Related
I'm doing a dataLayer push for e-commerce purchases. Following the GTM guide, the product items are in an array. The issue is pulling the data: all the guides I've seen mention using an array index -- e.g. transactionProduct.1.price to get the price for the 2nd item. But is not a robust solution: what if the user buys 100+ items? I can't hard-code the array index for this reason. So, how do I dynamically capture the properties in this case? I think I need to use the Custom JavaScript User-Defined Variable, but what would that look like (an example would be helpful)?
I believe I've figured it out:
If our dataLayer push looks like this:
window.dataLayer.push({
'event' : 'purchase',
'ecommerce': {
'transaction': {
'actionField': {
// ...
},
'products': // an array of objects...
}
}
});
Then, this GTM Custom JavaScript variable will return a list (of prices for each item):
function(){
var productList = {{NAME_OF_DATA_VARIABLE_ON_GTM_OF_ENTIRE_PUSHED_OBJECT}}.transaction.products;
return productList.map(function (obj) {
return obj.price;
});
}
I'm trying to access datalayer variables on add to cart event but it does not get tracked on the tag manager admin site
*The event is triggered but the values are not send
Datalayer push:
<script>
dataLayer.push({
'event': 'addToCart',
'ecommerce': {
'currencyCode': 'EUR',
'add': {
'products': [
{
'name': 'test',
'id': 'ZZZ232323',
'price': 33,
'brand': '',
'category': 'test',
'variant': '','quantity': 1
}
]
}
}
});
</script>
And i'm trying to access the datalayer to get the product name using:
dataLayer.find(x => x.event == 'addToCart').ecommerce.add.products[dataLayer.find(x => x.event == 'addToCart').ecommerce.add.products.length - 1].price
Image of google tag manager site
Data Layer Variables don't need to reference a specific step (array element) of the dataLayer. When you create a reference to a dataLayer variable, e.g. ecommerce, Google Tag Manager (GTM) will try to evaluate it at any given GTM event, but will fall back to undefined, or any other value, you specify.
This means, that if you fire your Facebook Pixel tracking code when the product data gets available (event = addToCart), a proper reference to the ecommerce data will have value in it. There are several options to get your product name.
You can create a general 'Ecommerce' variable, referencing ecommerce as Data Layer Variable Name. In your Facebook Pixel related code you will have to walk to the desired variable, and also take care for any possible missing values. However, this ecommerce variable can be used in several tags.
var productName = {{Ecommerce}}.add.products[0].name; //assuming you'll always have just one product in products array
Or, you can go for a specific variable, where your set 'Ecommerce - name of product added to cart', where you reference ecommerce.add.products[0].name. This way, you can simply assign this variable to the proper Facebook Pixel variable, using {{Ecommerce - name of product added to cart}}
I'd like to track a form CTA confirmation in GTM. There are 2 forms, Urls are the same, CTA are the same, but I'd like to collect those 2 CTAs in different events.
I did a GTM trigger with : when click ID = my CTA, I collect the information "when a user click to that CTA, an event is sent", but i'd like to collect that information, based on my form version, which is only differ in two areas of the website :
- In the Here is unique
- In the script :
var comparator = new Comparator();
comparator.init( { 'uniqKey' : "azeaze",
'surveyName' : "Here is unique",
'guidanceMode': false,
'url' : "/surveyProgress",
'save' : "/leadSave",
});
How can I consider in GTM the trigger :
When the CTA ID = XXX
AND
my 'surveyName = 1'
Fire an event.
If i would do that I could use 'surveyName = 2' for the other form.
The idea is, with the same CTA but with other HTML element in the "background" to fire 2 different events.
Thank you
In your trigger configuration click on plus sign next to your rules. This works as AND operator so all rules will have to be true. That way you can have 2 triggers - one for each CTA. For example:
You will have to setup "surveyName" variable. It could be either dataLayer variable or global JS variable, but that's up to you.
Is there any way I can create custom/conditional registration/profile fields in buddypress.
I tried Googling a lot about this, but I am not getting proper solution.
The condition what I am thinking of is :
I want to create 2/3 dropdowns, suppose if 1st one contains vehicles type(car, bike,),
then the second dropdown's option should change according to what user is choosing in dropdown 1.
any help would be appreciated.
Thanks a ton in advance. :-)
Currently there is no working plugin or hack for that. I saw such thing on some sites - but this is done via JavaScript and heavily modifying of a registration page source code.
It will be little tricky unless you touch register/resgistration.php source.
you can do like this if you little familiar with jquery.
Theres a hidden field ( id "signup_profile_field_ids" ) in buddypress registration form which tells server what fields in registration form, it will look like
<input type="hidden" name="signup_profile_field_ids" id="signup_profile_field_ids" value="5,11,1,10,32">
value of that field contains field ids of the registration form.
Now, you need to select a parent field to show conditional fields. you need to know parent and conditional field ids
now use this jquery code
<script type="text/javascript">
$(function(){
var childs = new Array("Child id 1","Child id 1"); // your child fields ids
var options = new Array("Car","Bike"); // your parent field options, notice option and child number is same, which means, one child for one option
var parent = "Parent Field id"; // place you parent field id
var currentFields = new Array();
currentFields = $("#signup_profile_field_ids").val().split(','); // take all current fields ids in an array
$.each(childs, function(index,value){
$('#field_'+value).parent().hide(); // hide all child fields first
currentFields.splice(currentFields.indexOf(value),1);
});
$("#signup_profile_field_ids").val( currentFields.join() );
$('#field_'+parent).after('<div id="conditional-fields-conteiner></div>"');
$('#field_'+parent).change(function(){
var option = $(this).val();
var appendField = childs[options.indexOf(option)];
var html = $("#field_"+appendField).parent().html();
$('#conditional-fields-conteiner').html(html);
$.each(childs, function(index,value){
currentFields.splice(currentFields.indexOf(value),1);
});
currentField[] = appendField;
$("#signup_profile_field_ids").val( currentFields.join() );
});
});
</script>
This may seems complex, but this is the easiest approach. if you are planning it in membership site, dont use it. user can manupulate conditional fields simply by editing html.
Theres also a plugin for this, going to release soon. I am developing it
http://rimonhabib.com/coming-up-next-buddypress-nested-conditional-fields/
Say you have a bunch of blog posts, and each post has a "title" and "category". How would you render all post titles on a single page, where there is a table for each group of posts that have the same "category" values?
I'm starting by sorting by category, so the posts in the same category are grouped together in the cursor:
Template.postLists.posts = function() {
return Posts.find({}, {sort:{category:1}});
}
But I'm struggling with iterating through this list in a template via {{#each}}, and using Handlebars to detect when I reach a new "category", so that I can start a new , and then end the when I'm at the end of the category.
Am I coming at this the wrong way, or is there an easy way to do this?
The solution I went with was that in my Template handler, instead of returning a cursor using Posts.find(), I created a JSON object that has a structure that can be processed by a handlebars template (an array of category objects, where each category has an array of posts):
Template.postLists.categorizedPosts = function() {
var allPosts = Posts.find({}, {sort:{category:1}}).fetch();
// Then I iterate over allPosts with a loop,
// creating a new array of this structure:
// for ...
var catPosts = [ { category:"cat1", posts: [ {post1}, {post2} ] },
{ category:"cat2", posts: [ {post3}, {post4}, {post5} ] },
// etc...
];
// end loop
return catPosts;
The the template is something like this (but with tables instead of UL, just using UL for a cleaner demo here):
{{#each categorizedPosts}}
{{category}}
<ul>
{{#each posts}}
<li>{{posts.title}}</li>
{{/each}}
</ul>
{{/each}}
Note that when you return an object like this (instead of a cursor object that Posts.find() returns), Meteor's templating engine loses the ability to intelligently detect when only one of the objects in the collection has changed, and patching the DOM instead of completely re-rendering the template. So in this case, the template is completely re-rendered even if a single Posts object is updated in the DB. That's the downside. But the upside is that it works ;)